sizeof(&array)返回什么?

use*_*750 30 c string pointers sizeof

问题是:为什么数组的地址等于它在C中的值?

#include <stdio.h>
#define N 10    
char str2[N]={"Hello"};
int main(){
    printf("sizeof(str2): %d bytes\n", sizeof(str2));
    printf("sizeof(&str2): %d bytes\n", sizeof(&str2));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

sizeof(str2): 10 bytes
sizeof(&str2): 4 bytes
Run Code Online (Sandbox Code Playgroud)

我知道str2单独是数组中第一个元素的地址str2.并且当str2它的参数何时sizeof返回整个数组str2的大小.

另外,&str2也是arr中第一个元素的地址,str2但是来自不同的类型(char (*)[N]==指向数组的指针).但是&str2当它是一个论证时,它是如何表现的sizeof

Gri*_*han 109

&str和之间的区别str,什么时候str被宣布为char str[10]

sizeof操作员:

6.5.3.4 sizeof运算符,1125:
sizeof运算符应用于数组类型时,结果是数组中的总字节数.

因此,根据您的声明,sizeof(str2)给出10个字节的完整数组大小(因为N定义为10,char大小为1个字节).
而在表达式中sizeof(&str2),&str2是数组的地址和系统中4字节的地址大小.(地址大小在某些系统中可能为8字节,例如64位).

另外,&str2也是arr中第一个元素的地址str2

没有,价值观明智两个 &str2str相同,但在语义上都是不同的.一个是10个字符数组的地址,而另一个是字符的地址.

你在自己的例子中看到的一个区别是它们是如何区别的(并且在这个答案中解释了@ouah).

  • 类型strchar[10]
  • 类型&strchar(*)[10]

第二: 下图将帮助您观察其他差异.

for declaration: 
#define N 10
char str2[N] = {"Hello"};

str2 Array in memory is something like:
----------------------------------------

str
+----+----+----+----+----+----+----+----+----+----++----+
|'H' |'e' |'l' |'l' |'o' |'\0'|'\0'|'\0'|'\0'|'\0'|| '@'|
+----+----+----+----+----+----+----+----+----+----++----+
 201   202  203 204  205   206  207  208  209  210   211
? ?     ?                                             ?
| |     |                                             |
|(str2) (str2 + 1)                                    | 
|                                                     |
|-----------------------------------------------------|
|201                                                  | 
|                                                     |
|                                                     |
(&str2) = 201                           (&str2 + 1) = 211


* assuming str address start from 201
* str[N] is 10 char long 201-210, partially initialized
* at uninitialized position, str2[i] = '\0'
* location 211 is unallocated, having garbage value,
  access to this location is illegal-Undefined Behavior
Run Code Online (Sandbox Code Playgroud)

对于上图,您可以编写代码:

#include <stdio.h>
#define N 10    
int main(){
   char str2[N]={"Hello"};

   printf("\n %p, %p\n",str2, str2+1);
   printf("\n %p, %p\n",(&str2), (&str2+1));
}  
Run Code Online (Sandbox Code Playgroud)

输出:

 0xbf67e142, 0xbf67e143

 0xbf67e142, 0xbf67e14c
Run Code Online (Sandbox Code Playgroud)

键盘链接:

请注意,第一行输出地址差异是一个字节,但在第二行中差异是10个字节,因为它的数组的指针(如上图所示).

根据指针数学规则,当你向指针变量添加1时,它开始指向它自己类型的下一个元素,这是10个字节差异的原因,因为&str2是数组地址.

第三个区别:

通过这样做*str2你可以访问第一个元素.虽然*(&str2)不会给你第一个元素,但它是第一个元素的地址.

一个例子将有助于:

#include <stdio.h>
#define N 10    
int main(){
   char str2[N]={"Hello"};
   printf("\n%p %c, %p %c\n",str2, *(str2), *(&str2), **(&str2));
}  
Run Code Online (Sandbox Code Playgroud)

输出:

0xbf587046 H, 0xbf587046 H
Run Code Online (Sandbox Code Playgroud)

键盘链接

在输出中

str2 gives  0xbf587046 
*(str2)     H 
*(&str2)    0xbf587046 
**(&str2)   H 
Run Code Online (Sandbox Code Playgroud)

这意味着*(&str2) == str2价值就是地址.因此*(str2) = **(&str2)价值观是H.

编辑: 上面我显示了区别&strstr哪里str是类型的数组char[10].

两者之间的差异char *str以及char str[]两者如何存储在内存中

假设我们有两个声明,如下所示:

char *str1 = "hello";   
char str2[] = "hello";  
Run Code Online (Sandbox Code Playgroud)

在上面的声明str1是一个指向char,即指向一个常数字符串文字(由保持第一个字符的地址h"hello"字符串).

C中的字符串是char[N](数组)类型,这就是为什么sizeof("hello")给出6因为"hello"字符串是6个字符长数组(包括\0nul,字符串终止,hello的类型是char[6]).

在内存中,您的"hello"字符串存储如下:

 str1         23   24   25   26   27   28
+----+      +----+----+----+----+----+----+
| 23 |      | h  | e  |  l | l  | o  | \0 |    
+----+      +----+----+----+----+----+----+
   +-----------?

here address of hello string is first address = 23.  
str1: is pointer capable to store address. 
"hello" consists of 6 chars
Run Code Online (Sandbox Code Playgroud)

char* str1 = "hello";基本上将字符串hello的地址存储到指针变量str1,如上图所示.

注意:如果您最近想要代码,则将更改更改str1为指向其他字符串.但你无法修改hello字符串.例如以下代码有效:

 char* str1 = "hello";  // str1 points to hello  str1-->"hello"
 str1 = "world";  //Now, str1 points to world  str1-->"world"
Run Code Online (Sandbox Code Playgroud)

现在str1指向其他常量字符串世界.

 str1         93   94   95   96   97   98 
+----+      +----+----+----+----+----+----+
| 93 |      | w  | o  |  r | l  | d  | \0 |    
+----+      +----+----+----+----+----+----+
   +-----------?

here address of world string is first address = 93.  
str1: value change to point string world. 
Run Code Online (Sandbox Code Playgroud)

需要注意的重要事项:str1指向常量字符串,因此您无法通过访问/索引内存位置来修改字符串,例如str1[i] = 'A'; 将是非法的,因为你在只读内存写,并且这种行为在运行时是未定义的(尽管没有编译错误,因为语法上它是正确的).

再次因为str1是一个指针sizeof(str1)将在同一台机器上给4.

我的以下代码及其运行:

#include <stdio.h>
int main(){
   char* str1="Hello";
   printf("\nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1));
   str1 = "world";
   printf("\nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1));
   return 1;
}  
Run Code Online (Sandbox Code Playgroud)

输出:

str1: Hello, address: 0x80485e8, sizeof(str1): 4
str1: world, address: 0x8048619, sizeof(str1): 4
Run Code Online (Sandbox Code Playgroud)

键盘链接

因此,要分配新字符串,我只需指定新字符串的地址.但是我不能打电话strcpy(),会尝试在只读内存位置写入,这是非法的.

在第二个声明中char str2[] = "hello";,str2[]是一个\0终止的字符数组(或字符串),但不是指针.注意因为在这个声明中大小没有给出默认大小,我们那个常量字符串"hello"的大小就是6.类型str2char[6].

当我们char str2[] = "hello";创建一个char数组并将hello字符串复制到该数组中时,str2不仅仅是指针而是存储完整字符串的数组.

它的概念在于.

       str2:
       103  104  105  106  107  108
      +----+----+----+----+----+----+
      | h  | e  |  l | l  | o  | \0 |    
      +----+----+----+----+----+----+
Run Code Online (Sandbox Code Playgroud)

而在这种情况下,最近在你的代码你不会允许这样做str2[] = "world";str2 = "world"感染这将是编译时错误.

示例代码:

#include<stdio.h>
int main(){
 char str2[] = "hello";
 str2[] = "world";
 str2 = "world"; 
 return 1; 
}
Run Code Online (Sandbox Code Playgroud)

编译错误:

In function 'main':
Line 4: error: expected expression before ']' token
Line 5: error: incompatible types in assignment
Run Code Online (Sandbox Code Playgroud)

Codescape链接

如果这个数组str2不是常数,我们可以修改它的内容,例如do str2[2] = 'A'完全有效.我们也可以调用strcpy来改变内容(并且地址空间不会改变)

       strcpy(str2, "world");

       str2:
       103  104  105  106  107  108
      +----+----+----+----+----+----+
      | w  | o  |  r | l  | d  | \0 |    
      +----+----+----+----+----+----+

      Note world coped into same memory space, address of world and hello
      string is name. 
Run Code Online (Sandbox Code Playgroud)

代码示例:

#include<stdio.h>
int main(){
 char str2[] = "hello";
 printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
 str2[2] = 'A';
 printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
 strcpy(str2, "world");
 printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
 return 1; 
}
Run Code Online (Sandbox Code Playgroud)

输出:

str2: hello, address: 0xbf58d056, sizeof(str2): 6
str2: heAlo, address: 0xbf58d056, sizeof(str2): 6
str2: world, address: 0xbf58d056, sizeof(str2): 6
Run Code Online (Sandbox Code Playgroud)

键盘链接

注意:字符串值在同一地址空间中是不同的.sizeof(str2)从旧答案中完全理解= 6,即以字节为单位的数组大小.

读取类似的描述约2维阵列读取:差异char* str[]char str[][]在存储器中,以及如何都店?


Oli*_*rth 20

&str2是一个指针.所以你只是看到平台上指针的大小.

  • 并非*必然*所有指针类型都是相同的大小,尽管对大多数实现来说都是如此. (8认同)

oua*_*uah 8

str2是类型char [10](即数组10 ofchar`)

&str2是类型char (*)[10](即指向数组10的指针char).

因此sizeof (&str2) 产生指针类型的对象的大小char (*)[10]