C标准允许指向不同类型的指针具有不同的大小,例如sizeof(char*) != sizeof(int*)是允许的.但是,它确实要求如果指针转换为a void*然后转换回其原始类型,则必须将其与原始值进行比较.因此,从逻辑上讲,sizeof(void*) >= sizeof(T*)对于所有类型T,正确吗?
在当今使用的大多数常见平台上(x86,PPC,ARM和64位变体等),所有指针的大小都等于本机寄存器大小(4或8字节),而不管指向的类型.是否存在任何深奥或嵌入式平台,其中指向不同类型的指针可能具有不同的大小?我特别询问数据指针,虽然我也有兴趣知道是否存在函数指针具有异常大小的平台.
我绝对不会问C++的指向成员的指针和指向成员的指针函数.这些在常见平台上具有不寻常的大小,甚至可以在一个平台内变化,具体取决于指针类的属性(非多态,单继承,多继承,虚继承或不完整类型).
指针的大小是否与其指向的类型的大小相同,或者指针总是具有固定大小?例如...
int x = 10;
int * xPtr = &x;
char y = 'a';
char * yPtr = &y;
std::cout << sizeof(x) << "\n";
std::cout << sizeof(xPtr) << "\n";
std::cout << sizeof(y) << "\n";
std::cout << sizeof(yPtr) << "\n";
Run Code Online (Sandbox Code Playgroud)
这会是什么输出?会sizeof(xPtr)返回4并sizeof(yPtr)返回1,或者2指针实际上会返回相同的大小吗?我问这个的原因是因为指针存储的是存储器地址而不是它们各自存储的地址的值.
最近,我看到这样的说法:
所有指针具有相同的大小是很常见的,但从技术上讲,指针类型具有不同的大小是可能的。
但后来我发现了这样的内容:
虽然指针的大小都是相同的,因为它们只存储内存地址,但我们必须知道它们指向什么类型的东西。
现在,我不确定以上哪种说法是正确的。第二个引用的语句看起来像是来自佛罗里达州立大学计算机科学的 C++ 笔记。
这就是为什么在我看来所有指针都应该具有相同的大小:
1)假设我们有:
int i = 0;
void* ptr = &i;
Run Code Online (Sandbox Code Playgroud)
现在,假设 C++ 标准允许指针具有不同的大小。进一步假设在某些任意机器/编译器上(因为标准允许),a 的void*大小为 2 字节,而 a 的int*大小为 4 字节。
现在,我认为这里有一个问题,即右侧有一个int*大小为 4 字节的 ,而左侧有一个void*大小为 2 字节的 。int*因此,当从到发生隐式转换时,void*将会丢失一些信息。
2)所有指针都保存地址。由于对于给定的机器,所有地址都具有相同的大小,因此所有指针也应该具有相同的大小是非常自然(合乎逻辑的)。
因此,我认为第二句话是正确的。
我的第一个问题是 C++ 标准对此有何规定?
我的第二个问题是,如果 C++ 标准确实允许指针具有不同的大小,那么有理由吗?我的意思是允许指针具有不同的大小对我来说似乎有点不自然(考虑到我上面解释的两点)。所以,我很确定标准委员会一定已经考虑到了这一点(指针可以有不同的大小),并且已经有理由允许指针有不同的大小。请注意,只有当标准确实允许指针具有不同的大小时,我才会问这个(第二个问题)。
c++ pointers void-pointers language-lawyer pointer-conversion
我想知道违反我在下面列出的假设的架构.此外,我想知道所有架构的假设是否都是错误的(也就是说,如果它们中的任何一个完全错误的话).
sizeof(int*)== sizeof(char*)== sizeof(void*)== sizeof(func_ptr*)
无论指向哪种数据类型,给定体系结构的所有指针的内存中表示都是相同的.
指针的内存中表示与与体系结构相同的位长的整数相同.
指针数据类型的乘法和除法仅被编译器禁止.注意:是的,我知道这是荒谬的.我的意思是 - 是否有硬件支持禁止这种不正确的用法?
所有指针值都可以转换为单个整数.换句话说,哪些架构仍然使用分段和偏移?
递增指针相当于添加sizeof(the pointed data type)指针存储的内存地址.如果p是int32*则p+1则等于4字节后的内存地址p.
我最习惯在连续的虚拟内存空间中使用指针.对于这种用法,我通常可以将它们视为数字线上的地址.请参阅堆栈溢出问题指针比较.
如何检查指针是否属于某种类型?
使用sizeof还不够.
我试图避免将id-numbers放入我的结构中来识别它们的类型.假设可能是gcc在进程中的某处放置了一个struct定义,并将定义映射到指针的已分配内存.如果这是真的,我认为会有一些检查指针类型.
发布我最有争议的一个回答后在这里,我不敢问几个问题,并最终在我的知识填补一些空白.
为什么不是一种((type_t *) x)被认为是有效左值的表达式,假设它x本身是指针和左值,而不仅仅是某个表达式?
我知道很多人会说"标准不允许它",但从逻辑的角度看它似乎是合理的.标准不允许的原因是什么?毕竟,任何两个指针都具有相同的大小,指针类型只是一个编译时抽象,指示在进行指针运算时应该应用的适当偏移量.
如果我使用char *s[],我可以执行以下操作:
char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"};
Run Code Online (Sandbox Code Playgroud)
有什么区别**s?我如何使用char **s而不是char *s[]在那种情况下?
示例:int main (int argc, char **argv)代替*argv[]
我有一个重复的打印,打印了一堆非空终止的,char*如下所示:
int len1, len2, len3, len4;
char *str1, *str2, *str3, *str4;
get_vals(message, val1, &str1, &len1);
get_vals(message, val2, &str2, &len2);
get_vals(message, val3, &str3, &len3);
get_vals(message, val4, &str4, &len4);
printf("%.*s %.*s %.*s %.*s", len1, str1, len2, str2, len3, str3, len4, str4);
Run Code Online (Sandbox Code Playgroud)
其中将指针get_vals设置char *为内存中的值并将 设置len为文本的长度。传入的值有可能char *被设置为NULL,如果是这样,长度字段将被设置为0。看来这个打印已经发生了很多次并且没有出现段错误,我认为由于长度说明符是0这样的事实,所以可能没有取消引用。然而,这总是安全的吗?也许它与操作系统或 libc 版本相关?是否值得像这样进行安全检查:
printf("%.*s %.*s %.*s %.*s",
len1, str1 ? str1 : "",
len2, str2 ? str2 : "",
len3, str3 ? …Run Code Online (Sandbox Code Playgroud) 好吧,对不起,这个问题更像是一个一般的文化(还没有找到确切的答案)。
如果我有类似的东西
char * Field
Run Code Online (Sandbox Code Playgroud)
或者
void * Field
Run Code Online (Sandbox Code Playgroud)
或者
double pointers
Run Code Online (Sandbox Code Playgroud)
假设 C 中的示例(我倾向于相信其他不直接处理指针的语言也是如此)