sizeof(&array) 返回什么?

2023-11-27

接下来的问题:在 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;
}

Output:

sizeof(str2): 10 bytes
sizeof(&str2): 4 bytes

我知道str2单独是数组中第一个元素的地址str2。而那个时候str2是一个参数sizeof它返回整个数组 str2 的大小。

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


之间的区别&str and str, when str被声明为char str[10]?

Read sizeof操作员:

6.5.3.4 sizeof 运算符,1125:
当您应用sizeof运算符转换为数组类型,结果是数组中的总字节数。

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

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

No,价值方面两者&str2 and str是相同的,但是在语义上两者是不同的。一个是 10 个字符数组的地址,另一个是字符的地址。

One您在自己的示例中看到它们之间的区别是(@ouah 在答案中解释了这一点)。

  • type of str is char[10]
  • type of &str is char(*)[10]

Second:遵循图表将帮助您观察其他差异。

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

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

#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));
}  

Output:

 0xbf67e142, 0xbf67e143

 0xbf67e142, 0xbf67e14c

A 键盘链接:

请注意,在第一行,输出地址相差一个字节,但在第二行,差异为 10 个字节,因为它是array's指针(如上图所示)。

根据指针算术规则,当指针变量加1时,它开始指向其自身类型的下一个元素。这就是 10 字节差异的原因,因为&str2是指向数组的地址。

Third不同之处:

通过做*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));
}  

output:

0xbf587046 H, 0xbf587046 H

键盘链接

在输出中

str2 gives  0xbf587046 
*(str2)     H 
*(&str2)    0xbf587046 
**(&str2)   H 

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

Edit:上面我展示了之间的区别&str and str where str是一个类型的数组char[10].

之间的区别char *str and char str[]以及两者如何存储在内存中

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

char *str1 = "hello";   
char str2[] = "hello";  

在上述声明中str1是一个指向char,它指向一个常量字符串文字(通过保存第一个字符的地址h in "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 the address of the hello string is the first address = 23.  
str1: is a pointer capable of storing an address. 
"hello" consists of 6 chars

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"

Now 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. 

重要注意事项: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;
}  

Output:

str1: Hello, address: 0x80485e8, sizeof(str1): 4
str1: world, address: 0x8048619, sizeof(str1): 4

键盘链接

因此,要分配一个新字符串,我只需分配一个新字符串的地址即可。但我不能打电话strcpy()它将尝试在只读内存位置上写入,这是非法的。

在第二个声明中char str2[] = "hello";, str2[] is an \0终止的字符(或字符串)数组,但不是指针。请注意,因为在此声明中未给出尺寸默认尺寸,我们看到常量字符串“hello”的大小为 6。类型str2 is char[6].

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

从概念上讲就像

       str2:
       103  104  105  106  107  108
      +----+----+----+----+----+----+
      | h  | e  |  l | l  | o  | \0 |    
      +----+----+----+----+----+----+

在这种情况下,最近在您的代码中您是not允许做str2[] = "world"; or str2 = "world",这将是编译时错误。

示例代码:

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

编译错误:

In function 'main':
Line 4: error: expected expression before ']' token
Line 5: error: incompatible types in assignment

代码景观链接

这个数组在哪里str2不是一个常量,我们可以修改它的内容,例如str2[2] = 'A'是完全有效的。我们也可以调用strcpy来改变内容(而地址空间不会改变)

       strcpy(str2, "world");

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

      Note that when "world" is copied into a same memory space, the addresses of both "world" and "hello"
      string are the same.  

代码示例:

#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; 
}

Output:

str2: hello, address: 0xbf58d056, sizeof(str2): 6
str2: heAlo, address: 0xbf58d056, sizeof(str2): 6
str2: world, address: 0xbf58d056, sizeof(str2): 6

键盘链接

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

要阅读有关二维数组的类似描述,请阅读:之间的区别char* str[] and char str[][]两者如何存储在内存中?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

sizeof(&array) 返回什么? 的相关文章

  • 为什么使用数组索引循环数组比指针访问慢?

    我正在读Kochan的书 Programming in C 在第 14 页的 指针和数组 部分中 264 他说 一般来说 索引数组的过程比执行索引过程花费更多的时间 访问指针内容的过程 其实这也是主要原因之一 为什么使用指针来访问数组的元素
  • C语言实现延时函数

    我想使用空循环实现延迟函数 但是完成一次循环所需的时间取决于编译器和机器 我希望我的程序自行确定时间并将程序延迟指定的时间 谁能给我任何想法如何做到这一点 注意 有一个名为delay 的函数可以将系统暂停指定的毫秒 是否可以在不使用此功能的
  • UI 线程正在阻塞调用 COM 对象的后台线程

    我正在开发一个通过第三方 COM 库与外部设备通信的应用程序 我试图让与设备的所有通信都通过后台线程 以防止通信问题搞砸我的应用程序 并消除在 UI 线程中进行通信所引入的一些其他复杂性 问题是 每当发生导致主 UI 线程阻塞的情况 即调用
  • 微软怎么能说WinAPI中一个字的大小是16位呢?

    我刚刚开始学习WinAPI 在MSDN中 对WORD数据类型提供了以下解释 WORD16 位无符号整数 范围是十进制 0 到 65535 该类型在 WinDef h 中声明如下 typedef 无符号短 WORD 很简单 而且它与我一直在使
  • 将视频上传/保存到数据库或文件系统

    我以前从未尝试过保存视频 所以我对此了解不多 我知道如果视频很小 我可以转换为字节数组并保存到数据库 但是为了提高效率 我想了解如何将任何上传的视频保存到我的服务器文件中 然后只保存该文件的文件路径我的数据库表中的视频 我完全不知道如何开始
  • 编译器消息“警告:格式‘%s’需要类型‘char *’,但参数 2 具有类型‘char (*)’”

    我正在尝试运行一个简单的 C 程序 但收到此错误 警告 格式 s 需要类型 char 但参数 2 的类型为 char 20 我在跑步Mac OS X v10 8 https en wikipedia org wiki OS X Mounta
  • Cookie 在 ASP.net 中失去价值

    我有以下设置 cookie 的代码 string locale DropDownList this LoginUser FindControl locale SelectedValue HttpCookie cookie new HttpC
  • 在 Linq 查询中使用动态列名称

    foreach Dimension dimensions in Enum GetValues typeof Dimension var r new ReferenceTable dimensions referenceItems List
  • 如何将输出重定向到 boost 日志?

    我有一个使用boost log的C 程序 我加载了用户提供的动态链接库 我想将 stderr 重定向到 boost 日志 以便用户的库随时执行以下操作 std cerr lt lt Some stuff 它产生相同的结果 BOOST LOG
  • WCF 服务中的缓冲区大小

    我们有一个 WCF 服务 它执行某些存储过程并将结果返回给 silverlight 客户端 某些存储过程最多返回 80K 行 下面给出的是 web config 中服务的设置
  • 当一对迭代器初始化时,向量是否知道先保留?

    考虑以下代码 struct MyData MyData const BYTE pData size t uSize bucket pData pData uSize std vector
  • Rx 在不同的线程上生产和消费

    我试图通过此处的示例代码来简化我的问题 我有一个生产者线程不断地输入数据 并且我尝试在批次之间添加时间延迟来对其进行批处理 以便 UI 有时间渲染它 但结果并不如预期 生产者和消费者似乎在同一个线程上 我不希望批处理缓冲区在正在生成的线程上
  • 引用与指针的执行速度

    我最近阅读了一篇关于托管语言是否比本机语言 特别是 C 与 C 慢 或快 的讨论 一位参与讨论的人士表示 托管语言的 JIT 编译器将能够对引用进行优化 而这在使用指针的语言中是不可能实现的 我想知道的是 对于引用而不是指针可以进行 什么样
  • 如何在 stl 模板中使用导出类 (__declspec(dllexport))?

    我正在使用导出的类 class declspec dllexport myclass private template declspec dllexport class std map
  • 在链表程序中使用模板时重载 C++ 中的 << 运算符

    我正在尝试实现一个链接列表 但是当我尝试重载 include
  • 使用 DataGridViewCheckboxCell 真正禁用 DataGridView 中的复选框

    有谁知道如何使用 DataGridViewCheckboxCell 禁用 DataGridView 中的复选框 我可以将其设置为只读 并设置背景颜色 但我无法让复选框本身显示为禁用状态 有什么想法吗 Guess 你必须自己画 http so
  • 小数精度

    我使用小数类型进行高精度计算 货币 但我今天遇到了这个简单的划分 1 1 37 这应该再次得到 37 http www wolframalpha com input i 1 2F 281 2F37 29 http www wolframal
  • 如何使用实体框架设置连接字符串

    我将 EF6 与 MySQL 结合使用 并有一个用于多个数据库的模型 我希望能够在我的表单中设置连接设置 如何以编程方式设置模型的连接字符串 你应该使用EntityConnectionFactory这就是您所需要的 public strin
  • 推断“x => { throw .. }”的 Lambda 与重载方法中的 Func 匹配吗?

    我不明白为什么 C 最终在以下 LINQPad 代码中执行不正确的扩展方法 void Main Actual Sync Action Expected Sync Action Run x gt x Dump Actual Async Tas
  • DbContext.SaveChangesAsync 异常处理

    当搭建新的脚手架时ApiController通过 Visual Studio 2013 中的异步操作和实体框架支持 某些方法可以包装DbContext SaveChangesAsync https msdn microsoft com en

随机推荐

  • 如何在正则表达式中匹配 12 小时时间 hh:mm?

    如何在正则表达式中匹配 12 小时时间 换句话说 匹配 12 30 但不匹配 14 74 谢谢 这应该有效 1 9 1 012 0 5 0 9
  • 如果我不告诉 C++ 中要抛出什么类型的对象,则抛出什么 throw 语句?

    由于没有显式抛出任何对象 以下代码异常终止 下面代码中的 throw 语句抛出了什么 int main try cout lt lt try throw catch cout lt lt catch return 0 throw不带参数只能
  • Bootstrap 轮播中的文本垂直居中

    我在 Bootstrap 4 中创建文本水平和垂直居中的轮播时遇到问题 我已经创建了bootply使用轮播 但文本位于左上角而不是屏幕中间 div class carousel slide div class carousel inner
  • RESTEasy 返回的集合中的根元素名称

    我在 JBoss AS 6 中通过 RestEasy 使用 JAX RS 当我的 JAX RS 资源返回项目集合 例如通过列表 时 RESTEasy 始终使用名称collection作为根元素 E g
  • 在一个文件中引用 typescript 定义,而不是所有 JS 文件?

    我正在 Visual Studio Code 中开发 Node JS Express 项目 并且想知道是否有一种方法可以在一个全局位置引用 TypeScript 定义 而不必在每个 JS 文件中重新引用定义 我看到 VSCode 支持 ts
  • 检索存档消息时未实现该功能

    我在用Openfire 3 8 2并安装了监控插件并启用了一对一聊天的存档 现在我可以在服务器端查看存档聊天 但是当我通过一个节时 我得到feature not implemented Request
  • 向数据框的“类”提供向量

    您知道如何向数据框提供名称向量来更改数据框的列或行名称 是否有类似的方法来提供名称向量来更改数据框中每列的类 当您使用 colClasses 通过 read table 读取数据帧时 可以执行此操作 如果数据框是在 R 内部创建的呢 DF
  • 使用 PhoneGap 覆盖 Android 后退按钮行为仅适用于第一页

    我正在使用 PhoneGap 1 5 0 jQuery 1 7 1 和 jQuery mobile 1 0 1 并尝试按照所述覆盖 Android 中的后退按钮here or here document addEventListener d
  • 如何使用QTextBlock?

    我对 C 和 Qt 完全陌生 我想填充一个QTextEdit对象与QTextBlocks 我怎么做 e g 如果我有一句话 鱼来了 我如何将每个单词放入自己的单词中QTextBlock并将该块添加到QTextEdit 或者我误解了如何QTe
  • 使用 GSON 的 Java 克隆对象

    我必须多次克隆一个对象 我的对象是不可序列化的 我正在使用以下功能 SuppressWarnings unchecked public static T cloneThroughJson T t Gson gson new Gson Str
  • htaccess 如果不是子域则添加 www,子域的则删除 www

    我正在尝试做到这一点 可能例子是最好的 所以 domain com gt www domain com www domain com gt www domain com subdomain domain com gt subdomain d
  • 学习多种语言[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 一旦你学会了一种语言 学习
  • Jogl着色器编程

    我刚刚开始着色器编程 GLSL 并使用 RenderMonkey 创建了一些 现在我想在我的 java 代码中使用这个着色器 有没有一些简单的例子来说明我如何做到这一点 我找到了一个非常简单的例子 int v gl glCreateShad
  • 两个外键,如何用laravel eloquent进行映射

    我在 MySQL 中有两个表 第一个表称为用户 第二个表称为游戏 表结构如下 users id 主要 email password 真正的名字 games id 主要 user one id 国外 用户得分 user two id 国外 用
  • Swift 有 String 的修剪方法吗?

    Swift 有 String 的修剪方法吗 例如 let result abc trim result abc 以下是删除开头和结尾的所有空格的方法String 测试示例斯威夫特2 0 let myString t t Let s trim
  • 如何在 Rails 中的关联模型上配置 pg_search 多重搜索?

    我正在将 pg search 添加到 Rails 应用程序中 我不完全理解配置 希望能在正确的方向上轻轻推动 首先 我已经或多或少地在我的应用程序上设置并运行了一个多模型网站 但我想将其扩展为搜索相关模型 例如 我有制造商 汽车 模型类 目
  • UITableView 的一部分周围的阴影

    我有一个UITableView有 4 个部分 现在我想向表格的特定部分添加阴影效果 而不是整个表格 我怎样才能完成这个任务 您将必须更改部分页眉和页脚以及该部分的所有单元格 Use tableView viewForFooterInSect
  • Internet Explorer 8 不传递 ajax 请求的会话 cookie

    我有简单的 php 应用程序 它适用于除 IE8 beta 2 之外的所有浏览器 当我尝试使用 Ajax 调用 jQuery post 方法 更新表字段时出现问题 使用 IE8 调试器 我发现 IE8 不发送会话 cookie 因此 php
  • 如何知道选择范围内是否存在链接元素

    在 Javascript 中 我想确定一个元素是否A元素 存在于给定范围 文本范围内 目的是确定用户当前的选择是否包含链接 我正在构建一个富文本编辑器控件 range 对象具有 commonAncestorContainer W3C 或pa
  • sizeof(&array) 返回什么?

    接下来的问题 在 C 语言中 为什么数组的地址等于它的值 include