为啥我不能声明 unsigned char* test = "Some text"

Posted

技术标签:

【中文标题】为啥我不能声明 unsigned char* test = "Some text"【英文标题】:Why I can't declare unsigned char* test = "Some text"为什么我不能声明 unsigned char* test = "Some text" 【发布时间】:2012-07-01 11:10:25 【问题描述】:

这在 Visual Studio 2010 中不起作用,它给了我以下错误

void main (void)

     unsigned char* test = "ATGST"; 


编辑 1:我的问题是为什么这适用于嵌入式系统,但不适用于 PC?

但是当我把它改成:

 char* test = "ATGST";  

它有效。

主要是我使用 C 为嵌入式系统编写代码,并且我使用 Visual Studio 来测试一些功能,因此我不必在微控制器上实时测试它。

我需要解释一下,因为微控制器接受第一个代码。

【问题讨论】:

您为什么期望它会起作用? charunsigned char 是两种不同的类型。 @ildjarn hmmmm 实际上 charunsigned char 可能 是同一类型。您可以强制 VS 将 generic char 类型视为 signed charunsigned char @Adriano : C++ 标准不同意:§3.9.1/1 "Plain charsigned charunsigned char 是三种不同的类型。" @ xsari3x : 那么那些编译器不符合要求。 对于托管(非嵌入式)系统,void main (void) 不正确。 =(嗯,大多数情况下;允许实现允许它,但没有充分的理由这样写。改用int main(void)。对于独立(嵌入式)系统,使用编译器支持的任何东西——很可能是@ 987654332@. @Adriano : 从charunsigned char 的转换必须是隐式的,但是从char*unsigned char* 的转换必须,就像从@987654337 的转换一样即使intlong 大小相同,@ 到long* 也不能。 【参考方案1】:

经过编辑以符合删除 C++ 标签和安抚嵌入标签。

首先,手头的问题是,您试图将char[] 文字传递给unsigned char*。您不能真正将 char 等同于 unsignedsigned,在这方面它有点特别。此外,字符串文字被赋予唯一的存储空间,并且永远不应该被修改。如果您要处理字符,则需要使用char[] 可以衰减到的标准 char*。你可以强行施放它,但我不喜欢推荐这样的东西。正如其中一位 cmets 指出的那样,这样做是安全的。实际上,这实际上是一种真正安全无忧的稀有事物。

但是对于 reinterpret_casting 提供足够限定的严格答案的空间太小了,这基本上是在告诉编译器您知道自己在做什么。这可能非常危险,只有在您对手头的问题非常确定时才应该这样做。 char 通常只是通用的,甚至没有签名或未签名。由于 unsigned char 的范围比 char 更大,并且通常 char 使用有符号 char 的正子集来描述字符(或任何其他可以适合的数据),如果您的数据不在扩展的正范围内,您重新出发。但是,一定要安全地符合环境和代码。

关于入口点函数-符合编辑

既然已经确定你在嵌入式系统上工作,这意味着你的程序很可能不需要返回任何东西,所以它可以保持void main()(它也可能需要非常不同的返回由给定的嵌入式系统指定,OP 最了解他的系统强加的要求)。在很多情况下,你可以保持 void 的原因是因为没有环境/操作系统可以安抚,没有人可以交流。但嵌入式系统也可能非常专业化,最好通过详细研究给定平台来满足要求(如果有的话)。

【讨论】:

如果语言是 C(如标记),则字符串文字的类型为 char [] 而不是 const char []。 MSVC 在这里似乎不符合标准。 @R.. :我认为这个答案是在 c++ 标签被编辑之前发布的。 @R.. 我只浏览 C++ 问题,只是注意到它已被删除。但是,是的,C 在这方面有所不同。我会编辑以补偿。 “我不喜欢推荐这样的东西” - 将指针投射到 (unsigned char *) 是你可以做的少数安全指针投射之一,你总是可以别名unsigned char 之类的任何东西。 Windows 始终是 2 的补码,因此您甚至不必担心 *((unsigned char*)ptr) != (unsigned char)(*ptr) 的理论可能性。尽管如此,如果它要指向一个字符串文字,那么它应该是 C 中的(const unsigned char*),即使该语言不需要它:如此接近推荐,但到目前为止...... 您对 main() 的咆哮无关紧要,而且可能不正确。这被明确标记为嵌入式,并且 OP 正在尝试在嵌入式系统和 Windows 上运行代码。在嵌入式系统上,代码非常好,在 Windows 上,它不会在严格符合的 C 编译器上编译(VC++ 不是)。以后在评论main()的格式之前先阅读this。【参考方案2】:

首先,您需要一个const。其次,char != unsigned char,还有(唯一的)!= signed char

字符串字面量的类型为const char[N]- 具有适当大小的N,因此只能转换为const char*。请注意,该语言有一个特殊规则,允许您隐式删除 const 但它仍然是 UB 来修改字符串文字,因此这样做是一个非常糟糕的主意。

微控制器的 C 实现在这方面是不合格的。最好简单地使用const char*,这是正确的,而不是试图破解 VS 接受不正确的代码。

【讨论】:

@xsari3x:实际上并没有我说的那么多。如果您想了解更多信息,则必须阅读 C 标准。 问题被标记为 C,并且在 C 中字符串文字的类型为 char[N],而不是 const char[N] @DanielFischer:我很确定这在 C 中和在 C++ 中一样被弃用。无论哪种情况,删除const 都一样糟糕。 @DanielFischer 这只是一个疏忽,因为 C 标准为我们带来了称为 UB 的好东西。不是沉迷于实践。改变文字意味着什么,赋予独特的存储空间。 const-ness 是理智问题,而不是语言问题。 @DeadMG 在 C 中,没有 const 可以放在这里。当然,将字符串文字分配给const char* 会更安全,因此建议这样做,但标准规定字符串文字的类型是char[N],而尝试修改的类型是UB。【参考方案3】:

我相信这是将字符串分配给 unsigned char * 的情况。

好吧,当你分配一个字符串值时,它会分配与字符相关的 ASCII 值,所以你应该使用 char * 代替 unsigned char *。

如果你想分配字符串、字符以外的值,那么你的实现是正确的。

希望对你有帮助。

【讨论】:

【参考方案4】:

如果您对文本使用字符类型,请使用不合格的字符。

如果您将字符类型用作数字,请使用无符号字符。 unsigned char,它至少为您提供 0 到 255 的范围。

更多信息:What is an unsigned char?

【讨论】:

【参考方案5】:

我的问题是为什么这适用于嵌入式系统,但不适用于 PC?

很可能是因为您不小心在 C++ 中编译 PC 代码,它的类型检查比 C 更严格。在 C 中,无论您使用 unsigned char 还是 plain char,代码都可以正常编译。

但是,正如其他答案中所建议的,您的代码存在一些问题需要修复。如果代码需要同时在嵌入式和 Windows 上运行,您应该将其重写为:

#ifdef _WIN32
int main (void)
#else
void main (void)
#endif

  const unsigned char* test = "ATGST"; 


【讨论】:

以上是关于为啥我不能声明 unsigned char* test = "Some text"的主要内容,如果未能解决你的问题,请参考以下文章

为啥打印 unsigned char 有时有效,有时无效?在 C 中

为啥将 unsigned char 用于 RGB 像素数据?

数组声明为 unsigned char 时的垃圾值

数据类型unsigned char表示范围(存储值的范围)是多少,为啥(写出计算过程)

在C语言中,unsigned char是啥类型?

C语言 请问signed char,unsigned char,short,unsigned sh