在下面的示例代码中,我使用string作为数组,如果str的名称是指向str的第一个元素的指针,在这种情况下,字符串的第一个字符,即s,str的大小,应该是8,但它给了6个。
#include <stdio.h>
char str[] = "string";
char *ptr = "string";
int main(void){
int first = sizeof(str);
int second = sizeof(str[0]);
int third = sizeof(ptr);
int size_of_array = sizeof(str)/sizeof(str[0]);
printf("the size is %d, %d, %d, %d", size_of_array, first, second, third);
return 0;
}
似乎str不是指针,str的大小不是ptr的大小?我对t 感到困惑
答案 0 :(得分:5)
长话短说;数组不指针,指针不数组。
由于隐式转换,你似乎能够在需要指针 1 的上下文中使用一个数组(并且很遗憾),开发人员会混淆两者。
你自己的代码片段是一个完美的例子,因为数组不是指针,指针不是数组。
1。“重要的是要注意,在许多情况下,数组会衰减为指针,因为这是混淆的常见原因。” - Ed S.
你的sizeof
将运行变量的“真实”类型,这就是为什么你得到的数字与你认为 array-names 等同于指针。
只是让读者清楚这个问题;数组不是指针,指针不是数组..
答案 1 :(得分:5)
首先,问题的主要内容:编译器严格按照声明大小处理sizeof。在下面的代码中,假设指针变量保存一个32位(4字节)地址:
char str1[] = "abcd";
char *pstr = str1;
// str1 is declared to be a fixed array of 5 chars (4+nul)
size_t str1size = sizeof(str1); // str1size = 5;
// pstr is declared to be a 32 bit pointer to a memory address.
size_t pstrSize = sizeof(pstr) // size of a 32 bit pointer; 4.
要掌握你所看到的结果,请回顾一下数组和指针变量的差异,(其中大多数人都认为这些差异很少)。
数组和指针变量之间C的核心差异是
如果你想真正地用C语言中的数组和指针包围你的第一个,我根本无法强调。除此之外,他们的关系充其量只是乱伦。指针变量位于地址,如数组(或任何其他变量)。但与数组不同,它们还将地址作为值。数组是他们的地址。
第一个最好的证明如下:
char str1[] = "abcd";
char *pstr = NULL;
pstr = str1; // ok. pstr holds the address *at* str1.
str1[0] = *pstr; // ok. copies 'a' on to 'a'.
pstr++; // ok. increment the address held in pstr by one item (char) size.
str1[0] = *pstr; // ok. copies 'b' over 'a'.
pstr = str1+1; // ok. pstr holds the address *at* str1 + one item (char) size.
str1 = pstr; // does not compile. str1's address cannot be changed.
请注意,指针变量本身包含地址,而固定数组是地址。因此,最后的陈述完全正确。
pstr = str1; // ok. put the str1 address in pstr, a pointer variable.
答案 2 :(得分:1)
是和否,str是一个数组,但当它出现在表达式中时,它会转换为指向数组第一个成员的指针。
奇怪的是,当你执行sizeof(str)时,它应该给你一个7而不是6,因为它包含NUL终止符。
s t r i n g \ 0
如果您使用了strlen(),它将返回6.
答案 3 :(得分:1)
奇怪的是,之前的答案都没有直接解决标题中提出的问题。
不,数组的名称不是指向其第一个元素的指针。
在大多数表达式中,作为数组的表达式将转换为指向第一个元素的指针。因为这在大多数表达式中都会发生,所以人们倾向于将数组视为指针。但是,有四个例外。当数组是sizeof
,_Alignof
或&
的操作数时,或者当它是用于初始化数组的字符串文字时,不会将数组转换为指针。因为您的一个示例使用数组作为sizeof
的操作数,所以它使用数组,而不是指向第一个元素的指针。
因此,在sizeof(str[0])
中,首先解析str[0]
。在此子表达式中,str
不是sizeof
的操作数,因此它将转换为指针。然后该指针与下标运算符一起使用,结果是数组的第一个元素。然后sizeof
计算该元素的大小,即1。
在sizeof(str)
中,str
是sizeof
的操作数。所以不转换为指针;这是阵列。然后sizeof
计算该数组的大小,即7。
请注意,此转换不仅适用于标识符(名称);它适用于任何表达式。因此,如果p
是一个指向数组的指针,如float (*p)[4];
所声明的那样,则*p
是一个包含四个浮点数的数组,因此它被转换为指向float的指针(当它不是sizeof
,_Alignof
或&
)的操作数。