我正在学习编程范例教程并做一些与记忆相关的练习。我刚刚提取了两个问题(请忘记代码的样子,抱歉这是错误的代码,但我只是想从中学习指针的东西)。原始代码使lsearch尽可能通用,因此它使用所有指针。
我有一个关于访问数组元素的问题:
当我们访问数组a[]
的第四个元素时,我们使用*(a+3)
;
当我们访问字符串数组char * names[]
的第3个元素时,我们使用*(char**)((char*)names+sizeof(char*)*2)
。
我们是否假设数组的元素在内存中连续保存?
关于访问字符串数组元素的问题2:为什么我们需要在(char*)
(基地址)前面添加names
,我尝试不添加(char*)
和代码因分段错误而崩溃。我打印的是(char*)
的大小,它是8,而sizeof(names)
是32.为什么我们需要(char*)
?我真的认为地址是32位,如果我们把它转换成8位,计算机应该很难找到它指向的元素。
谢谢
#include<iostream>
#include<string>
#include<typeinfo>
int main()
{
int a[5] = {1,2,3,4,5};
std::cout << *(a+3) << std::endl;
char* names[4] = {"James", "Dustin", "Rich", "Ed"};
std::cout << *(char**)((char*)names+2*sizeof(char*)) << std::endl;
//std::cout << sizeof(names) << " " << sizeof(char*) << std::endl;
}
以下是stanford 107的原始代码。
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int StrCmp(void* vp1, void* vp2)
{
char *s1 = *(char**)vp1;
char *s2 = *(char**)vp2;
if(strcmp(s1,s2)==0){
return 0;
}
return 1;
}
char ** lsearch(void *key, void* base, int size, int elemSize, int (*cmpFn)(void *, void *))
{
for(int i=0; i<size; ++i){
char* addr = (char*) base + elemSize *i;
if (cmpFn(key, addr)==0) return (char**)addr;
}
return NULL;
}
int main()
{
char *notes[] = {"Ab", "F#", "B", "Gb", "D"};
char* favorStr = "F#";
char ** found = lsearch(&favorStr,notes,5,sizeof(char*),StrCmp);
if(found!=NULL) cout << *(char**)found << endl;
else cout << "not found" << endl;
}
答案 0 :(得分:3)
根据C ++标准(8.3.4阵列)
1 ...数组类型的对象包含一个连续分配的非空集 N个T型子对象。
从帖子应用数组定义意味着只有四个指针(数组的元素)到字符串文字才会在连续的内存范围内分配。这段内存不包括字符串文字本身。
在C ++中,字符串文字具有常量字符数组的类型。当它们被用作这样的初始化器时
char* names[4] = {"James", "Dustin", "Rich", "Ed"};
然后它们被隐式转换为const char *
类型的指针,指向数组的第一个元素。
所以定义像
这样的数组会更好const char* names[4] = {"James", "Dustin", "Rich", "Ed"};
如果要输出数组的第三个元素(考虑到它是一个指针),那么你必须写
std::cout << ( const void * ) ( names + 2 ) << std::endl;
如果要输出此元素指向的字符串文字,则应编写简单的
std::cout << *( names + 2 ) << std::endl;
至于表达
*(char**)((char*)names+2*sizeof(char*))
然后子表达式(char*)names
重新解释类型为char *[4] like an array pf type
char [4 * sizeof(char *)]的数组。所以表达
(char*)names+2*sizeof(char*)
产生与表达式
相同的值( names + 2 )
例如声明
std::cout << ( const void * )( names + 2 ) << std::endl;
和
std::cout << ( void * )( (char*)names + 2*sizeof(char*) ) << std::endl;
将产生相同的输出
我认为如果要运行这个示范程序会更清楚
#include <iostream>
int main()
{
const char* names[4] = {"James", "Dustin", "Rich", "Ed"};
for ( size_t i = 0; i < 4; i++ )
{
std::cout << ( const void * )( names + i ) << std::endl;
}
std::cout << std::endl;
for ( size_t i = 0; i < 4; i++ )
{
std::cout << ( const void * )*( names + i ) << std::endl;
}
std::cout << std::endl;
for ( size_t i = 0; i < 4; i++ )
{
std::cout << ( const void * )( ( char * )names + i * sizeof( char * ) ) << std::endl;
}
std::cout << std::endl;
for ( size_t i = 0; i < 4; i++ )
{
std::cout << ( const void * )*( ( const char ** )( ( const char * )names + i * sizeof( char * ) ) ) << std::endl;
}
std::cout << std::endl;
}
程序输出可能看起来像
0x7fffc0f639f0
0x7fffc0f639f8
0x7fffc0f63a00
0x7fffc0f63a08
0x40d884
0x40d88a
0x40d891
0x40d896
0x7fffc0f639f0
0x7fffc0f639f8
0x7fffc0f63a00
0x7fffc0f63a08
0x40d884
0x40d88a
0x40d891
0x40d896
在此程序中,( names + 0 )
,( names + 1 )
,( names + 2 )
,( names + 3 )
是索引为0, 1, 2, 3
的数组名称的相应元素的地址。
表达式*( names + 0 )
,*( names + 1 )
,*( names + 2 )
,*( names + 3 )
是存储在此元素中的值。
表达式( char * )names + i * sizeof( char * )
其中i位于0-3
范围内
是数组元素的相同地址。和表达
*((const char **)((const char *)names + i * sizeof(char *)))给出数组元素的相同值。