【问题标题】:Explanation of sizeof() with various data types in C++C++中各种数据类型sizeof()的解释
【发布时间】:2015-10-01 08:49:50
【问题描述】:

附加问题(1 分): 假设我们使用的是 32 位 Windows 操作系统 和 C/C++ 程序。请估计以下的sizeof()(单位:字节)

• char str[] = “Hello” ;
• char *p = str ;
• int n = 10;
Please calculate:
• sizeof ( str ) = __________
• sizeof ( p ) = __________
• sizeof ( n ) = __________

大家好,

我正试图围绕这个 C++ 中相当基本的概念展开思考。我会告诉你我认为正确的答案是什么,看看我是否在正确的轨道上。对于第一个 sizeof(str),我相信它总共是 6 个字节。我注意到其他问题中的一个模式,即这些类型的字符串总是添加 1 个字节。 (5 个字母 +1)。我的问题是,这个“+1”来自什么?至于第二个下来,这只是指指针的大小,p,对吗?哪个总是 4 个字节的大小?最后,第三个,我相信只是指一个 int 的大小,n。据我所知,所有整数的大小都是 4 个字节正确吗?这是否意味着所有整数都是 4 个字节,无论它是 10 还是 10000 或任何其他数字。也非常感谢并张开双臂接受有关此主题的任何其他重要信息!谢谢!

【问题讨论】:

  • 第一个是6,后两个取决于实现。
  • 对于 32 位 Windows,整数和指针都是 4 个字节。

标签: c++ sizeof string-literals


【解决方案1】:
char str[] = "Hello" ;

相当于:

char str[] = {'H', 'e', 'l', 'l', 'o', '\0'};

标准保证sizeof(char)1。因此sizeof(str)6

指针和int 的大小始终取决于平台。

【讨论】:

    【解决方案2】:

    好吧,这是我在 stackoverflow 上的第一个答案

    第一个问题:

     char str[] = "Hello";
    

    在 C/C++ 字符数组中,需要一个空终止符('\0')或(NULL)来标识字符数组的结尾,每当我们读取字符数组时,指针都会放在第一个索引处,它会循环直到我们发现空终止字符。因此它的大小是 6。

    注意空终止字符因编译器而异(据我所知),通常它们使用'\0'。 你也可以使用零(0);

    char s[] = {'H','E','L','L','O',0};
    

    或'NULL'

    char s[] = {'H','E','L','L','O',NULL};
    

    第二个问题:

    char *p = str 
    

    字符指针'p'存储字符数组'str'的地址 它指向字符数组的第一个索引并存储地址。 这是4个字节。因此你得到

    • sizeof ( p ) = 4 // p holds the address of str

    如果您使用了 *p(p 处的值),那么您将收到 1 的值。

     • sizeof ( *p ) = 1 // Now *p is value at p i.e first element in
                     character array = 'H' which is of size 1 byte
    

    第三个问题

    int n = 10
    

    这显然会在 32 位系统上为您提供 4 字节(8 位)的大小。

    同样,大小也因编译器而异。

    谈论你的最后一个问题

    这是否意味着所有整数都是 4 个字节,无论它是 10 还是 10000,或者 任何其他号码

    答案是肯定的和否定的 对于 C/C++ 的 16 位编译器,signed int 的范围是 -32768 到 32767。

    对于 32 位编译器,范围是 -2147483648 到 +2147483647

    此范围内的任何数字(带符号的 int 类型)在 Turbo C 等 32 位编译器上将占用 4 个字节

    也非常感谢您提供有关此主题的任何其他重要信息 张开双臂接受了

    趣事 对于以上如果

    int n = 2147483648 //note the extra 1 
    

    仍在打印或存储

    2147483647 in n
    

    试试看(在 32 位编译器上)

    其次 在 C++ 中用于字符串,即

    string str = "Hello";
    • str.size() = 5 // note: its not 6 
    

    我希望我回答了您的问题并提供了更多信息。

    【讨论】:

    • int n = 2147483648 是未定义行为,可能打印为 2147483647、2147483648、-2147483647、0 或 "you're fired",或者格式化您的硬盘而不是打印任何内容。
    • @MSalters 感谢您指出“未定义的行为”,我会记住的。
    【解决方案3】:

    我注意到其他问题的模式总是 1 个字节 添加到这些类型的字符串中。 (5 个字母 +1)。我的问题是,什么 这是来自“+1”吗?

    那 1 个字节用于空终止,即“\0”。 想一想。

    如果你使用 strlen(在运行时计算)而不是 sizeof(在编译时计算),strlen() 从第一个字符开始扫描字符串,增加计数,移动到下一个字符,必须有某个字符哪个字符串必须标记它的结束,对吗?这就是空终止的用途。

    据我所知,所有整数的大小都是 4 字节正确吗?

    C++ 标准没有以字节为单位指定整数类型的大小, 但它指定了他们必须遵守的最小范围。

    这里已经解释过了。 [What does the C++ standard state the size of int, long type to be?

    良好的做法是始终使用标准定义来避免此类混淆。

    看看

    “stdint.h”或“cstdint”

    头文件,如果你在 linux 上。不确定 Windows。

    int8_t、int16_t、int32_t、uint8_t、uint16_t、uint32_t

    这些使代码更具可读性。

    【讨论】:

    • sizeof 不扫描字符串的大小。它是一个编译时间常数。
    • stdint.h 是 C 标准头文件。 cstdint 是 C++ 标头,而不是 cstdint.h
    【解决方案4】:

    在 C++ 中,如果我们将一个数组传递给sizeof,我们会得到它的长度;不是它衰减到的大小的指针。字符串文字是带有空终止符的n 字符数组。

    所以

    const char str[] = "foobar";
    

    sizeof(str) == 7 因为实际上它会像这样在内存中设置:

    const char str[] = {'f', 'o', 'o', 'b', 'a', 'r', '\0'};
    

    这是一个编译时常量,一旦定义了数组,编译器就知道了。

    如果您将指针指向该数组const char *strp = str,则为sizeof(strp) == sizeof(char*)


    至于intT*(其中T 是任何对象类型)的大小,由实现定义。但是sizeof(T*) == sizeof(U*) == sizeof(void*) 其中TU 是任何对象类型。

    您获得的唯一保证是sizeof(char) == 1。其他任何事情都取决于实施。

    来自N4140(C++14 草案标准)

    § 3.9.1 基本类型
    2 - 有五种标准有符号整数类型:“signed char”、“short int”、“int”、“long int”和“long 长整数”。在此列表中,每种类型提供的存储空间至少与列表中它前面的类型一样多。 也可能有实现定义的扩展有符号整数类型。标准和扩展签名 整数类型统称为有符号整数类型。普通整数具有建议的自然大小 执行环境的架构46;提供其他有符号整数类型以满足特殊要求 需要。

    所以你得到的实际保证是:

    sizeof(signed char) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
    

    signed charchar 大小相同,但类型不同,unsigned char 大小相同,但又是另一个不同类型。


    另一方面,大多数系统都是这样的:

    64位操作系统,sizeof(T*) == 8
    32位操作系统,sizeof(T*) == 4

    在 64 位和 32 位系统上 sizeof(int) 通常 == 4

    其中T 是任何object 类型

    【讨论】:

    • 我不认为sizeof(T*)== sizeof(void*) 是有保证的。 sizeof(T*) &lt;= sizeof(void*) 很可能是因为 void* 必须能够保存指向 any 对象的指针,但是特别邪恶的编译器可能会向 T* 添加不需要的填充位。稍微不那么邪恶的是,指向数组的T* 可能会保存缓存的数组大小。这在调试模式下很有用。但是由于没有 void[ ] void* 可能不会得到相同的计数。
    • @MSalters 数组的大小不是指针本身的一部分,而是分配为指针之前的几个字节。无论如何,如果我要这样做,我就会这样做。但是不,标准保证指向对象的指针的大小总是相同的,void* 是指向未知类型对象的指针。这就是为什么将 void* 转换为函数指针类型是未定义行为的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-26
    • 1970-01-01
    • 2010-11-18
    • 2018-04-23
    • 2013-12-24
    • 2015-06-27
    • 1970-01-01
    相关资源
    最近更新 更多