发信人: spadger (imdx), 信区: Circuit
标  题: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 14:14:01 2020), 站内
  
update
------------------------------------------
可以用宏来定义字符串,解决一致性问题,编译器也可以优化成同一个地址,
这样相当于绕过编译器的类型检查。但只是绕过了问题,依然无法解释AC5和gcc的行为。
  
编译结果更让人惊掉下巴,改用宏实现以后,AC5和AC6均可以编译通过
AC5编译完尺寸占用0x9c40,AC6是0xcbd0,都是最大尺寸优化。后者比前者大了30%多。
  
AC5.06 -O3优化编译结果:
  
Load Region LR_IROM1 (Base: 0x08002000, Size: 0x00009c40, Max: 0x0000e000, ABSOLUTE, COMPRESSED[0x00009a18])
  
AC6.13.1 -O3优化直接报空间不足,-Oz优化编译结果:
  
Load Region LR_IROM1 (Base: 0x08002000, Size: 0x0000cbd0, Max: 0x0000e000, ABSOLUTE, COMPRESSED[0x0000ca58])
  
  
MDK中遇到的问题,AC6正常编译,AC5报错。简化以后如下:
------------------------------------------
#include <stdio.h>
const char * const str1 = "str1";
const char * str2 = str1;
int main() {
     printf("%s - %s\n", str1, str2);
     return 0;
}
------------------------------------------
str1是个指向常量字符串的常量指针,用它来初始化另外一个常量字符串。
本意是想定义两个指向同一个静态常量字符串的常量指针。目的是减小代码体积。
  
MDK 编译器V6.13.1,C99模式,正常编译正常运行,无错误无警告。
MDK 编译器V5.06,C99模式,报错:
     error:  #28: expression must have a constant value
     V5.06似乎不认为str1是个常量,打开编译器的GNU扩展,一样报错。
  
换到Linux下试了下,gcc报错,g++正常,编译器版本7.4.0,好奇怪。
  
  
--
  
※ 修改:·spadger 于 Jan 14 17:11:28 2020 修改本文·[FROM: 36.45.168.*]
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

0/0      124
spadger 的帖子 spadger 的图片    查看原帖 回复: 124
第 1 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:25:34 2020), 站内
  
你把声明第一个“变量”的关键字const去掉试试
有的编译器用了const的确就不分配内存单元,而是把它变成代码一部分,自然也就不存在地址了
  
要我写,我估计是这么写的
  
#include <stdio.h>  
char *str1[] = "str1";  
char *str2 = str1[0];  
int main() {  
      printf("%s - %s\n", str1[], str2);  
      return 0;  
}
  
  
【 在 spadger 的大作中提到: 】
: MDK中遇到的问题,AC6正常编译,AC5报错。简化以后如下:
  
--
※ 修改:·dismoon 于 Jan 14 15:33:41 2020 修改本文·[FROM: 117.63.26.*]
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 2 楼

发信人: lanmp (-_-!谁的大腿), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:29:09 2020), 站内
  
你这都是变量啊。常量就应该在ROM里啊
【 在 dismoon 的大作中提到: 】
: 你把声明第一个“变量”的关键字const去掉试试
: 有的编译器用了const的确就不分配内存单元,而是把它变成代码一部分,自然也就不存在地址了
: 要我写,我估计是这么写的
: ...................
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 106.38.10.*]

第 3 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:31:10 2020), 站内
  
  
楼主不是就要变量吗,不是变量哪里来的地址指针啊
  
【 在 lanmp 的大作中提到: 】
: 你这都是变量啊。常量就应该在ROM里啊
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 4 楼

发信人: lanmp (-_-!谁的大腿), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:33:45 2020), 站内
  
常量为什么不能有地址指针?
【 在 dismoon 的大作中提到: 】
: 楼主不是就要变量吗,不是变量哪里来的地址指针啊
:  
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 106.38.10.*]

第 5 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:36:07 2020), 站内
  
  
有的编译器对常量的处理方式是直接放代码里面,不在执行内存里面。
不在内存里面=没有地址
  
【 在 lanmp 的大作中提到: 】
: 常量为什么不能有地址指针?
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 6 楼

发信人: lanmp (-_-!谁的大腿), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:40:19 2020), 站内
  
你说的代码是ROM么,哪个编译器的常量不放在ROM里?不太明白不在内存里面=没有地址,ROM不能访问么?
【 在 dismoon 的大作中提到: 】
: 有的编译器对常量的处理方式是直接放代码里面,不在执行内存里面。
: 不在内存里面=没有地址
:  
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 106.38.10.*]

第 7 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:43:44 2020), 站内
  
  
我这么解释你可能更容易理解一点
假设有代码1
int a=100;
int b=a;
然后编译器就会先弄4个字节的地址出来存放a,然后让b得到a对应的地址里面的值;
  
然后有代码2
const int a=100;
int b=a;
好了,代码2不同的编译器有不同的编译方法,有的比较浪费的编译器,会以然按照代码1的方法编译,只是后继代码中不允许改变a的值。而有的比较节约的编译器,索性就不分配4个字节给a了,相对的,第一句代码在这种编译器眼里,就等同于
#define a 100
  
这样子,你写int b=a自然没有问题,因为等于是int b=100;
当时当你用int *b=a的时候,就会出错,因为100不是一个变量,自然没有地址
  
  
【 在 lanmp 的大作中提到: 】
: 常量为什么不能有地址指针?
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 8 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:49:08 2020), 站内
  
  
哦,你的本意是减小代码长度,我的办法可能舍本求末了
容我再三思一下.....
  
【 在 spadger 的大作中提到: 】
: MDK中遇到的问题,AC6正常编译,AC5报错。简化以后如下:
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 9 楼

发信人: lanmp (-_-!谁的大腿), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 15:56:13 2020), 站内
  
你挺会举例子,如果不是100而是ABCDEFG呢?你准备怎么给b赋值?你最后那个报错难道不是类型不匹配的问题么?
【 在 dismoon 的大作中提到: 】
: 我这么解释你可能更容易理解一点
: 假设有代码1
: int a=100;
: ...................
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 106.38.10.*]

第 10 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:00:19 2020), 站内
  
  
.......
不是100而是ABCD你不会用 *char[]?
类型不匹配不正是因为不是变量了所以不存在类型了吗?
  
【 在 lanmp 的大作中提到: 】
: 你挺会举例子,如果不是100而是ABCDEFG呢?你准备怎么给b赋值?你最后那个报错难道不是类型不匹配的问题么?
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 11 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:19:37 2020), 站内
  
看了下回帖,大侠你是认真的么?
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: .......
: 不是100而是ABCD你不会用 *char[]?
: 类型不匹配不正是因为不是变量了所以不存在类型了吗?
: ...................
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 12 楼

发信人: javaboy (喝了咖啡就话多-_-;), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:21:24 2020), 站内
  
我mdk不熟。
  
这种情况用alias比较稳妥。
http://www.keil.com/support/man/docs/armcc/armcc_chr1359124980906.htm
  
或者把str1和str2声明成extern的,在汇编或者ld脚本里提供实现。
  
在C里这不是标准行为,得依赖各种扩展。所以束手束脚的。
  
【 在 spadger (imdx) 的大作中提到: 】
: MDK中遇到的问题,AC6正常编译,AC5报错。简化以后如下:
: ------------------------------------------
: #include <stdio.h>
: const char * const str1 = "str1";
: const char * str2 = str1;
: int main() {
:     printf("%s - %s\n", str1, str2);
:     return 0;
: }
: ------------------------------------------
: str1是个指向常量字符串的常量指针,用它来初始化另外一个常量字符串。
: 本意是想定义两个指向同一个静态常量字符串的常量指针。目的是减小代码体积。
: MDK 编译器V6.13.1,C99模式,正常编译正常运行,无错误无警告。
: MDK 编译器V5.06,C99模式,报错:
:     error:  #28: expression must have a constant value
:     V5.06似乎不认为str1是个常量,打开编译器的GNU扩展,一样报错。
: 换到Linux下试了下,gcc报错,g++正常,编译器版本7.4.0,好奇怪。
  
  
--
  
※ 修改:·javaboy 于 Jan 14 16:22:16 2020 修改本文·[FROM: 116.234.18.*]
※ 来源:·水木社区 newsmth.net·[FROM: 116.234.18.*]

第 13 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:22:43 2020), 站内
  
我理解错你的问题了吗?
  
  
【 在 spadger 的大作中提到: 】
: 看了下回帖,大侠你是认真的么?
:  
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 14 楼

发信人: tom6bj (tom), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:24:49 2020), 站内
  
const char* str1 = "abc";
const char* str2 = "abc";
  
这种情况大概率也会被优化成同一个地址
  
不过跨文件就难说了
  
【 在 spadger (imdx) 的大作中提到: 】
: MDK中遇到的问题,AC6正常编译,AC5报错。简化以后如下:
: ------------------------------------------
: #include <stdio.h>
: ...................
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 106.121.177.*]

第 15 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:30:29 2020), 站内
  
  
重新看了一下,你的意思是说,str2声明的时候认为str1可以改变,不是一个常量,所以你用const不行?
严格的编译器的确不行,因为你的str1虽然是个常量指针,但是str2指向str1,编译器没那么聪明,不会“推理”出因为str1是常量,所以str2也是常量
我那个回复的确是粗看一下理解错你的意思了,但是我都不用常量的写法的确可以有效规避报错
嗯,而且const这个关键词我一般是不用的,因为我经常碰到不同编译器对我的代码不同编译。
你根据自己ram大小和rom大小调整一下吧,但是这年头,还有你这么在乎代码尺寸的吗?
  
【 在 spadger 的大作中提到: 】
: 看了下回帖,大侠你是认真的么?
:  
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 16 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:36:10 2020), 站内
  
  
const char Const_str[] = "abc";
const char* str1=Const_str[0];
const char* str2=Const_str[0];
  
这样子也没有什么大概率了,就是强制了
  
  
【 在 tom6bj 的大作中提到: 】
: const char* str1 = "abc";
: const char* str2 = "abc";
: 这种情况大概率也会被优化成同一个地址
: ...................
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 17 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:45:23 2020), 站内
  
const非常有用,如果你不加,很多代码实际上占用FLASH和SRAM两份。
即同时占用.text段和.data段。
如果你的器件资源裕量非常大,那确实无所谓。
问题是我现在不管AC5还是AC6,不开最大体积优化模式代码都装不下,ROM是64kB的。
当然这是另外一个问题,这里不讨论。
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: 标  题: Re: 帮忙看个C语言常量字符串问题
: 发信站: 水木社区 (Tue Jan 14 16:30:29 2020), 站内
:  
:  
: 重新看了一下,你的意思是说,str2声明的时候认为str1可以改变,不是一个常量,所以你用const不行?
~~~~~~~~~~~~~出错时编译器的错误提示就是这个意思。
  
: 严格的编译器的确不行,因为你的str1虽然是个常量指针,但是str2指向str1,编译器没那么聪明,不会“推理”出因为str1是常量,所以str2也是常量
~~~~~~~~~~~~~str1是个指向常量指针,它本身也是常量,即str1++也是不行的。这个对编译器的信息量足够多了,而且,AC6的C编译器和GCC的g++都是可以正常编译的,说明不存在编译器不够聪明的问题。
  
: 我那个回复的确是粗看一下理解错你的意思了,但是我都不用常量的写法的确可以有效规避报错
: 嗯,而且const这个关键词我一般是不用的,因为我经常碰到不同编译器对我的代码不同编译。
: 你根据自己ram大小和rom大小调整一下吧,但是这年头,还有你这么在乎代码尺寸的吗?
:  
: 【 在 spadger 的大作中提到: 】
: : 看了下回帖,大侠你是认真的么?
: :  
:  
: --
:  
: ※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]
  
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 18 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 16:55:16 2020), 站内
  
如果用const之后代码没有到ram,只占了flash一份,那回到我刚开始理解错了之后讨论的问题
你会遇到很多“被优化”的问题。
我遇到过这类问题都是最后靠翻汇编找出来的,所以后来权衡了一下时间成本得失,才最终放弃了const这个关键词,能不用尽量不用。
当然我都是小代码项目,这个要根据个人项目区别对待
  
【 在 spadger 的大作中提到: 】
: const非常有用,如果你不加,很多代码实际上占用FLASH和SRAM两份。
: 即同时占用.text段和.data段。
: 如果你的器件资源裕量非常大,那确实无所谓。
: ...................
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 19 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:01:13 2020), 站内
  
const都不用,估计volatile更不会用,那确实开优化容易出问题。
我的观点是:如果代码不开优化正常,开优化异常,那一定是代码有问题。
我常年都是开着最大尺寸优化,AC5是-O3,AC6是-Oz,毕竟能用小容量器件就不用大容量。
之前AC6.9开-Oz有个bug,开-Oz编译器会挂掉,还好AC6.13解决了。
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: 如果用const之后代码没有到ram,只占了flash一份,那回到我刚开始理解错了之后讨论的问题
: 你会遇到很多“被优化”的问题。
: 我遇到过这类问题都是最后靠翻汇编找出来的,所以后来权衡了一下时间成本得失,才最终放弃了const这个关键词,能不用尽量不用。
: ...................
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 20 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:08:25 2020), 站内
  
我有个原则volatile只对第一级直接接收P1,2,3,4管脚变化值的变量用。
其他时候反正我都是直读寄存器,也没啥烦恼
【 在 spadger 的大作中提到: 】
: const都不用,估计volatile更不会用,那确实开优化容易出问题。
: 我的观点是:如果代码不开优化正常,开优化异常,那一定是代码有问题。
: 我常年都是开着最大尺寸优化,AC5是-O3,AC6是-Oz,毕竟能用小容量器件就不用大容量。
: ...................
--
  
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.63.26.*]

第 21 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:14:21 2020), 站内
  
你试试我写给tom的那三行代码,不用宏,先定义一个字符串,然后两个指针指向它的策略呢
【 在 spadger 的大作中提到: 】
: update
--
  
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.63.26.*]

第 22 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:14:31 2020), 站内
  
那你觉得下面这个函数有没有问题?
  
void Delay(uint16_t n)
{
     while(n > 0)
     {
         n--;
     }
}
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: 我有个原则volatile只对第一级直接接收P1,2,3,4管脚变化值的变量用。
: 其他时候反正我都是直读寄存器,也没啥烦恼
  
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 23 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:15:54 2020), 站内
  
看原文,我更新了。其实有解决方案可以绕过这个问题。
不过本帖的目的不是找解决方案,是探讨为什么AC5和gcc会有这种行为模式。
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: 你试试我写给tom的那三行代码,不用宏,先定义一个字符串,然后两个指针指向它的策略呢
  
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 24 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:22:28 2020), 站内
  
要看传递参数n是从什么地方得到的,如果和外部没关系,这个延迟函数完全没问题。如果n随时更新(或者函数执行时有中断会改写n,我建议弄个局部变量拷贝下n
【在 spadger 的大作中提到: 】
: 那你觉得下面这个函数有没有问题?
: void Delay(uint16_t n)
: {
: ...................
--
  
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.63.26.*]

第 25 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:34:08 2020), 站内
  
你可以到汇编上看看给str2赋值用了什么指令,我估计还是对const解读不同造成的。
【 在 spadger 的大作中提到: 】
: 看原文,我更新了。其实有解决方案可以绕过这个问题。
: 不过本帖的目的不是找解决方案,是探讨为什么AC5和gcc会有这种行为模式。
:
--
  
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.63.26.*]

第 26 楼

发信人: lanmp (-_-!谁的大腿), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:36:18 2020), 站内
  
你说的不对,但是我不想再和你辩论了
【 在 dismoon 的大作中提到: 】
: .......
: 不是100而是ABCD你不会用 *char[]?
: 类型不匹配不正是因为不是变量了所以不存在类型了吗?
: ...................
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 211.103.82.*]

第 27 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:37:53 2020), 站内
  
是不对,贴子看一半后面没看,仔细看完是我理解错了
【 在 lanmp 的大作中提到: 】
: 你说的不对,但是我不想再和你辩论了
--
  
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.63.26.*]

第 28 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:40:00 2020), 站内
  
是的,他好像不明白值传递和volatile的作用。
  
【 在 lanmp (-_-!谁的大腿) 的大作中提到: 】
: 标  题: Re: 帮忙看个C语言常量字符串问题
: 发信站: 水木社区 (Tue Jan 14 17:36:18 2020), 站内
:  
: 你说的不对,但是我不想再和你辩论了
: 【 在 dismoon 的大作中提到: 】
: : .......
: : 不是100而是ABCD你不会用 *char[]?
: : 类型不匹配不正是因为不是变量了所以不存在类型了吗?
: : ...................
:  
: --
:  
: ※ 来源:·水木社区 http://www.newsmth.net·[FROM: 211.103.82.*]
  
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 29 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:43:42 2020), 站内
  
大侠,你这个答案要是去面试,面试官会拍桌子的..
当然你是大老板,不需要去面试。
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: 标  题: Re: 帮忙看个C语言常量字符串问题
: 发信站: 水木社区 (Tue Jan 14 17:22:28 2020), 站内
:  
: 要看传递参数n是从什么地方得到的,如果和外部没关系,这个延迟函数完全没问题。如果n随时更新(或者函数执行时有中断会改写n,我建议弄个局部变量拷贝下n
: 【在 spadger 的大作中提到: 】
: : 那你觉得下面这个函数有没有问题?
: : void Delay(uint16_t n)
: : {
: : ...................
: --
:  
: ※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.63.26.*]
  
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 30 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:44:24 2020), 站内
  
......我是从经验中总结出为了省一点空间优化反而会带来更多问题,主动放弃优化节省开发时间
【 在 spadger 的大作中提到: 】
: 是的,他好像不明白值传递和volatile的作用。
:
--
  
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.63.26.*]

第 31 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 17:47:44 2020), 站内
  
码农我是半道出家,我只管产品按时没质量问题.....而且现在器件真的已经越来越多资源了,现在pc上写代码还有多少人用union?今后mcu上也是,没必要为了优化死扣
【 在 spadger 的大作中提到: 】
: 大侠,你这个答案要是去面试,面试官会拍桌子的..
: 当然你是大老板,不需要去面试。
:
--
  
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.63.26.*]

第 32 楼

发信人: zkr (Just Waiting.), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 20:56:10 2020), 站内
  
搜索了一番并且尝试理解了一下C99
感觉是个implementation defined行为,编译器不认可OK,多推断一步也OK
  
6.7.8-4 全局生存期初始化要么是常量表达式要么是字符串常量
-> str1 OK; str2要看str1算不算常量表达式
  
6.6 看下来感觉str1不算是常量表达式,
6.6-10留了个implementation defined的口子,就是
An implementation may accept other forms of constant expressions.
  
-> str2默认不行,但如果编译器愿意多折腾则OK。
  
  
C++的const含义和C不一样,这个case没深究过。
  
  
有一个类似的回答,供参考
https://stackoverflow.com/questions/3025050/error-initializer-element-is-not-constant-when-trying-to-initialize-variable-w
  
  
The New C Standard似乎部分讨论了这个问题,没细看,感觉意思相仿
  
  
【 在 spadger (imdx) 的大作中提到: 】
: 标  题: 帮忙看个C语言常量字符串问题
: 发信站: 水木社区 (Tue Jan 14 14:14:01 2020), 站内
:  
: MDK中遇到的问题,AC6正常编译,AC5报错。简化以后如下:
: ------------------------------------------
: #include <stdio.h>
: const char * const str1 = "str1";
: const char * str2 = str1;
: int main() {
:     printf("%s - %s\n", str1, str2);
:     return 0;
: }
:  
: ※ 修改:·spadger 于 Jan 14 17:11:28 2020 修改本文·[FROM: 36.45.168.*]
: ※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]
  
  
--
  
※ 修改:·zkr 于 Jan 14 20:57:43 2020 修改本文·[FROM: 123.112.159.*]
※ 来源:·水木社区 newsmth.net·[FROM: 123.112.159.*]

第 33 楼

发信人: lanmp (-_-!谁的大腿), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 21:01:05 2020), 站内
  
感觉这个靠谱,原来是初始化的问题
【 在 zkr 的大作中提到: 】
: 搜索了一番并且尝试理解了一下C99
: 感觉是个implementation defined行为,编译器不认可OK,多推断一步也OK
: 6.7.8-4 全局生存期初始化要么是常量表达式要么是字符串常量
: ...................
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 123.122.47.*]

第 34 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 21:52:47 2020), 站内
  
回帖写半天,说含有不合适内容,晕...
  
【 在 zkr (Just Waiting.) 的大作中提到: 】
: 搜索了一番并且尝试理解了一下C99
: 感觉是个implementation defined行为,编译器不认可OK,多推断一步也OK
: 6.7.8-4 全局生存期初始化要么是常量表达式要么是字符串常量
: ...................
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 35 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Tue Jan 14 22:08:44 2020), 站内
  
stackoverflow的链接不错,作者要解决的问题和我要解决的问题是完全一样的。
全局生存期初始化不一定常量表达式或者字符串常量,至少函数是可以的。。
  
下面这个例子 gcc 7.4.0 编译运行一切正常。
  
void func(void)
{
         printf("func\n");
}
typedef void (*func_type)(void);
func_type f = func;
int main() {
         f();
         return 0;
}
  
函数可以理解为常量指针,可以用来初始化,不知道const char *const(注意
不是const char*)定义的指针就不行.
  
  
【 在 zkr (Just Waiting.) 的大作中提到: 】
: 标  题: Re: 帮忙看个C语言常量字符串问题
: 发信站: 水木社区 (Tue Jan 14 20:56:10 2020), 站内
:  
: 搜索了一番并且尝试理解了一下C99
: 感觉是个implementation defined行为,编译器不认可OK,多推断一步也OK
:  
: 6.7.8-4 全局生存期初始化要么是常量表达式要么是字符串常量
: -> str1 OK; str2要看str1算不算常量表达式
:  
: 6.6 看下来感觉str1不算是常量表达式,
: 6.6-10留了个implementation defined的口子,就是
: An implementation may accept other forms of constant expressions.
:  
: -> str2默认不行,但如果编译器愿意多折腾则OK。
:  
:  
: C++的const含义和C不一样,这个case没深究过。
:  
:  
: 有一个类似的回答,供参考
: https://stackoverflow.com/questions/3025050/error-initializer-element-is-not-constant-when-trying-to-initialize-variable-w
:  
:  
: The New C Standard似乎部分讨论了这个问题,没细看,感觉意思相仿
:  
:  
: 【 在 spadger (imdx) 的大作中提到: 】
: : 标  题: 帮忙看个C语言常量字符串问题
: : 发信站: 水木社区 (Tue Jan 14 14:14:01 2020), 站内
: :  
: : MDK中遇到的问题,AC6正常编译,AC5报错。简化以后如下:
: : ------------------------------------------
: : #include <stdio.h>
: : const char * const str1 = "str1";
: : const char * str2 = str1;
: : int main() {
: :     printf("%s - %s\n", str1, str2);
: :     return 0;
: : }
: :  
: : ※ 修改:·spadger 于 Jan 14 17:11:28 2020 修改本文·[FROM: 36.45.168.*]
: : ※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]
:  
:  
: --
:  
: ※ 修改:·zkr 于 Jan 14 20:57:43 2020 修改本文·[FROM: 123.112.159.*]
: ※ 来源:·水木社区 newsmth.net·[FROM: 123.112.159.*]
  
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.168.*]

第 36 楼

发信人: zkr (Just Waiting.), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 08:13:45 2020), 站内
  
  
【 在 spadger (imdx) 的大作中提到: 】
: stackoverflow的链接不错,作者要解决的问题和我要解决的问题是完全一样的。
: 全局生存期初始化不一定常量表达式或者字符串常量,至少函数是可以的。。
函数可做两个理解
  
# 调用函数并返回值,这是不行的。
   6.6 - 3指出:函数调用不属于常量表达式。
   Constant expressions shall not contain ... function-call ...  
   except when they are contained within a subexpression that is not evaluated.
  
   C++似乎有constexpr,和C不同。
  
# 函数名称作为地址,这是可以的。
   6.6 - 7指出:常量表达式包含地址常量。
   6.6 - 9指出:地址常量,里边包含了函数的地址。
   An address constant is ... a pointer to a function designator ...;
   it shall be created ... implicitly by the use of an expression of array or  
   function type.
  
  
供参考
  
--
  
※ 修改:·zkr 于 Jan 15 08:16:29 2020 修改本文·[FROM: 113.45.181.*]
※ 来源:·水木社区 newsmth.net·[FROM: 113.45.181.*]

第 37 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 09:40:40 2020), 站内
  
其实不用去翻标准,按这条准则来判断就可以,
即:*运行时*不变的常量才能用来做Initializer.
1)常量表达式、常量字符串自然满足。
2)函数调用只能发生在运行时,因此不满足。
3)函数名字编译时确定,运行时不变,可以满足。
4)const char *str1定义的字符串常量,str1自身运行时是可变的,位置在RAM,不满足。
5)const char * const str1定义的字符串常量,str1运行时不变,位置在ROM,理论上
    完全可以用来做Initializer,确实也有C编译器可以,比如MDK的AC6,也有编译器不
    支持,这里应该算是C标准一个小小的缺陷。
  
【 在 zkr (Just Waiting.) 的大作中提到: 】
: 标  题: Re: 帮忙看个C语言常量字符串问题
: 发信站: 水木社区 (Wed Jan 15 08:13:45 2020), 站内
:  
:  
: 【 在 spadger (imdx) 的大作中提到: 】
: : stackoverflow的链接不错,作者要解决的问题和我要解决的问题是完全一样的。
: : 全局生存期初始化不一定常量表达式或者字符串常量,至少函数是可以的。。
: 函数可做两个理解
:  
: # 调用函数并返回值,这是不行的。
:   6.6 - 3指出:函数调用不属于常量表达式。
:   Constant expressions shall not contain ... function-call ...  
:   except when they are contained within a subexpression that is not evaluated.
:  
:   C++似乎有constexpr,和C不同。
:  
: # 函数名称作为地址,这是可以的。
:   6.6 - 7指出:常量表达式包含地址常量。const char * const字符串属于这种。
:   6.6 - 9指出:地址常量,里边包含了函数的地址。
:   An address constant is ... a pointer to a function designator ...;
:   it shall be created ... implicitly by the use of an expression of array or  
:   function type.
:  
:  
: 供参考
:  
: --
:  
: ※ 修改:·zkr 于 Jan 15 08:16:29 2020 修改本文·[FROM: 113.45.181.*]
: ※ 来源:·水木社区 newsmth.net·[FROM: 113.45.181.*]
  
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.173.*]

第 38 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 10:07:04 2020), 站内
  
一个小问题,关于程序有bug的标准。
你认为,一段代码,选最大编译优化,在任何编译环境都能通过,且程序执行符合你的本意才算没有bug吗?
我觉的,最大编译优化本来就是编译器用简陋的AI在揣摸程序员的意思,比如经典的
A=1;
A=2;
A=3;
优化成直接A=3;
这属于傻AI脑补。
【 在 spadger 的大作中提到: 】
: 其实不用去翻标准,按这条准则来判断就可以,
: 即:*运行时*不变的常量才能用来做Initializer.
: 1)常量表达式、常量字符串自然满足。
: ...................
--
  
※ 来源:·水木社区 http://m.newsmth.net·[FROM: 117.136.46.*]

第 39 楼

发信人: lanmp (-_-!谁的大腿), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 10:16:47 2020), 站内
  
让你不用volatile
【 在 dismoon 的大作中提到: 】
: 一个小问题,关于程序有bug的标准。
: 你认为,一段代码,选最大编译优化,在任何编译环境都能通过,且程序执行符合你的本意才算没有bug吗?
: 我觉的,最大编译优化本来就是编译器用简陋的AI在揣摸程序员的意思,比如经典的
: ...................
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 223.104.3.*]

第 40 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 10:56:16 2020), 站内
  
学习下volatile吧,不会早晚踩坑。
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: 一个小问题,关于程序有bug的标准。
: 你认为,一段代码,选最大编译优化,在任何编译环境都能通过,且程序执行符合你的本意才算没有bug吗?
: 我觉的,最大编译优化本来就是编译器用简陋的AI在揣摸程序员的意思,比如经典的
: ...................
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.173.*]

第 41 楼

发信人: zkr (Just Waiting.), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 11:08:28 2020), 站内
  
往多里说,你的观点要求编译器基于给定平台的特征/假设,进行推断。。。
  
在C里,const的意思差不多就是不要通过这个变量往里写东西。。。没别的了。
  
希望编译器想更多就有点困难了。对于特定平台或许问题少很多。
  
  
【 在 spadger (imdx) 的大作中提到: 】
: 其实不用去翻标准,按这条准则来判断就可以,
: 即:*运行时*不变的常量才能用来做Initializer.
: 1)常量表达式、常量字符串自然满足。
: ...................
  
--
  
※ 修改:·zkr 于 Jan 15 11:24:51 2020 修改本文·[FROM: 113.45.181.*]
※ 来源:·水木社区 newsmth.net·[FROM: 113.45.181.*]

第 42 楼

发信人: zkr (Just Waiting.), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 11:15:46 2020), 站内
  
编译器的正确优化是满足标准规定的,即程序行为在变换前后是一致的。
不正确的优化是编译器的Bug。
  
  
你写的代码不满足你的预期是因为你幻想了标准规定的行为。
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: 一个小问题,关于程序有bug的标准。
: 你认为,一段代码,选最大编译优化,在任何编译环境都能通过,且程序执行符合你的本意才算没有bug吗?
: 我觉的,最大编译优化本来就是编译器用简陋的AI在揣摸程序员的意思,比如经典的
: ...................
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 113.45.181.*]

第 43 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 11:17:47 2020), 站内
  


其实我平时也是有优化等级的,但是到目前为止,我的代码风格决定了我其实完全不需要使用volatile....
  
首先说明,我没做过你那么大的工程,一般我的一个项目也就5~6K大小,但是
我用C写程序说穿了就是“因为C代码可以让我给每一个变量起一个容易看懂的名字方便维护
从逻辑上说,我还是在用汇编写程序。
汇编里面有volatile这个概念吗?
  
我的代码,优化不优化,一般也就差了那么三四十个字节的大小,全程是从机器的角度去思考怎么处理问题,所以还真没啥用,声明变量对我来说就是给个地址罢了....
  
【 在 spadger 的大作中提到: 】
: 学习下volatile吧,不会早晚踩坑。
:  
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]
  

第 44 楼

发信人: zkr (Just Waiting.), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 11:24:37 2020), 站内
  
另外,我感觉,C标准定义的时候就是编译期不要做太多的事儿,简单的可以有。
  
所以,对于常量表达式来说,简单字面值化简可以有,复杂的推断基本给ban了。
  
运行个函数,生成个常量表,这个需求挺自然的。。。
  
【 在 spadger (imdx) 的大作中提到: 】
: 其实不用去翻标准,按这条准则来判断就可以,
: 即:*运行时*不变的常量才能用来做Initializer.
: 1)常量表达式、常量字符串自然满足。
: ...................
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 113.45.181.*]

第 45 楼

发信人: dismoon (伐开心要包包), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 11:27:15 2020), 站内
  
  
顺带一提,我写的函数里,95%左右的语句都是一个寄存器怎么样,一个寄存器怎么样,基本就是汇编打包。
volatile,const对我才是不必要的
  
【 在 lanmp 的大作中提到: 】
: 让你不用volatile
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 117.63.26.*]

第 46 楼

发信人: zkr (Just Waiting.), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 11:30:41 2020), 站内
  
看一下你用的REG的定义吧
  
【 在 dismoon (伐开心要包包) 的大作中提到: 】
: [upload=1][/upload]
: 其实我平时也是有优化等级的,但是到目前为止,我的代码风格决定了我其实完全不需要使用volatile....
: 首先说明,我没做过你那么大的工程,一般我的一个项目也就5~6K大小,但是
: ...................
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 113.45.181.*]

第 47 楼

发信人: lanmp (-_-!谁的大腿), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 11:30:53 2020), 站内
  
你的问题不能怪编译器,上面的帖子里你在指责编译器。
【 在 dismoon 的大作中提到: 】
: 顺带一提,我写的函数里,95%左右的语句都是一个寄存器怎么样,一个寄存器怎么样,基本就是汇编打包。
: volatile,const对我才是不必要的
:  
  
--
  
※ 来源:·水木社区 http://www.newsmth.net·[FROM: 106.38.10.*]

第 48 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 12:26:16 2020), 站内
  
其实字符串常量表,和函数的常量表一样的自然。
只是默认用 const char * 定义的字符串常量,指针本身不是常量,
而 const char * const 定义的是,这一种用得少,许多编译器就不会去实现了。
  
【 在 zkr (Just Waiting.) 的大作中提到: 】
: 标  题: Re: 帮忙看个C语言常量字符串问题
: 发信站: 水木社区 (Wed Jan 15 11:24:37 2020), 站内
:  
: 另外,我感觉,C标准定义的时候就是编译期不要做太多的事儿,简单的可以有。
:  
: 所以,对于常量表达式来说,简单字面值化简可以有,复杂的推断基本给ban了。
:  
: 运行个函数,生成个常量表,这个需求挺自然的。。。
:  
: 【 在 spadger (imdx) 的大作中提到: 】
: : 其实不用去翻标准,按这条准则来判断就可以,
: : 即:*运行时*不变的常量才能用来做Initializer.
: : 1)常量表达式、常量字符串自然满足。
: : ...................
:  
: --
:  
: ※ 来源:·水木社区 newsmth.net·[FROM: 113.45.181.*]
  
  
--
  
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.173.*]

第 49 楼

发信人: spadger (imdx), 信区: Circuit
标  题: Re: 帮忙看个C语言常量字符串问题
发信站: 水木社区 (Wed Jan 15 12:29:47 2020), 站内
  
想起老郭相声里那个火箭用煤的梗了...
  
【 在 lanmp (-_-!谁的大腿) 的大作中提到: 】
: 你的问题不能怪编译器,上面的帖子里你在指责编译器。
  
  
--
  
※ 修改:·spadger 于 Jan 15 12:30:43 2020 修改本文·[FROM: 36.45.173.*]
※ 来源:·水木社区 newsmth.net·[FROM: 36.45.173.*]

剩下的 75 个回复
0/0      124
spadger 的帖子 spadger 的图片    查看原帖 回复: 124





发到邮箱
联系我们