C:在 sizeof() 内转换数组时出现意外结果

标签 c sizeof

我不得不经历一种(另一种)对我而言意想不到的 C 行为,这次是使用 sizeof

我的目标是尝试理解这种行为背后的原因以及我应该如何解决这个问题。我对替代解决方案并不真正感兴趣,因为我的主要目标是了解这里发生的情况及其原因。

我通过 #define-C 预处理器宏 (#define CONST "foobar") 定义了一个字符串,并在以下函数中使用它:

senddata(uint8_t * data, uint32_t len)

因为 - 取决于实现/架构,但至少在 x86 - char 默认情况下是签名的,所以在以这种方式调用它时,我收到了有关“签名性不同[ence]”的警告:

senddata(CONST, sizeof(CONST))

因此,我必须在每次 senddata 调用时强制转换它 (senddata((uint8_t *)CONST, sizeof(CONST)))。

由于我的代码中对 CONST 的所有使用实际上都会被强制转换为 uint8_t ,所以我想我只需更改定义即可:

#define CONST "foobar" -> #define CONST ((uint8_t *)"foobar")

并且不必再为进一步的类型转换而烦恼。

虽然这确实消除了警告并且一切看起来都很好,但我必须以艰难的方式学习,在这些情况下 sizeof() 实际上不再返回字符串的长度,而是返回数据类型的大小,在这种情况下案例uint8_t *

对我来说,这似乎并不明显。

所以我的问题是 2 折:

  • 1)在上述情况下我该如何做?
  • 2)为什么会这样?
  • 3) 我如何才能知道这一点?这并不意味着(被动)攻击,而是:我应该凭借什么先验知识才能得出这样的结论:这行不通?

我在某处学到的一些半知半解的知识可能会对此产生影响,但我不太确定从中得到什么:sizeof() 不是一个普通函数,而是一个运算符(例如 sizeof int 无需括号即可工作)。

我的另一个猜测:"foobar"是一个字符数组,而(char *)"foobar"是一个指针。

最佳答案

您已经快到了,需要记住的是,sizeof 适用于操作数的类型,而不是值。

引用 C11,第 §6.5.3.4 章

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

例如,sizeof("array")sizeof(char[6])相同,因为"array"是类型为 char[6]。鉴于 char 的大小定义为 1,它将产生结果 6。

但是,当您对 sizeof 的操作数使用强制转换时,它会将该强制转换视为上述定义的类型。因此,诸如 sizeof ((char*)"array") 之类的内容将与 sizeof (char*) 相同。根据您的平台,它可以生成值 48,即指针的大小(指向 char)。

关于C:在 sizeof() 内转换数组时出现意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61081291/

相关文章:

c - 如何使用一个定义或函数使用 C 打印任何变量类型?

c - 二维字符数组出现问题,程序无法打印

c++ - Fsync 太快?

c++ - 字符串数据类型如何存储为字节

c++ - sizeof 继续返回 4 而不是实际大小

c++ - 从 sizeof 自动扣除的类型在 Visual Studio C++ 和 GCC 之间不同

c - 为什么 sizeof(long long) 返回 8?

检查命令行参数是否为负数

c++ - 基于 bool toggle 的高效对称比较

c - 如何检查结构体中的变量是否未在 C 中使用?