我不得不经历一种(另一种)对我而言意想不到的 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*)
相同。根据您的平台,它可以生成值 4
或 8
,即指针的大小(指向 char
)。
关于C:在 sizeof() 内转换数组时出现意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61081291/