@老虎会游泳,意思是,拿某个寄存器来存
read_next,而不存入栈上了好像写入数组末尾之后,是未定义行为。这么说,编译器认为
read_next未被修改也无不可。。哎,还是等写完之后,再加
restrict试试吧。反正也不是啥速度极为严苛的场景,只是想顺便学学restrict而已
指针本身是否被优化到寄存器与restrict无关。如果不对指针进行取地址操作,它就可以被优化到寄存器。
char buf[16]; char *read_next = buf, *write_next = buf + 16; *write_next = '\0'; // 此时 read_next 岂不就被修改了吗?(假设 read_next 就在 buf 后面)编译器咋会放心把
read_next缓存至寄存器的。。
@老虎会游泳,老虎用
restrict的情景多吗?我是不是要写完那个小插件,再试试加
restrict,才理解得更快呢。。
@老虎会游泳,感觉 43 楼的设计,没法加
restrict?那岂不读指针和结束指针都没法缓存至寄存器,每次读取前都要读一次内存?(因为编译器认为,写指针可能会修改
char *read_next, *end?)
@老虎会游泳,画了个草图,容易理解:
@老虎会游泳,写指针 和 读指针,都指向同一块缓冲区。只是写指针写入过后的字符对象,都绝不再读取。(因为写指针不会超出读指针,如上所述)
@老虎会游泳,只是【通过
char * restrict修改后,不再使用其他别名】,也不行?因为解析了一个字符,并写入后,就不再需要读取这个及之前的字符对象了
@老虎会游泳,“对象类型”是指非函数类型。。
另外,只是指向
char类型的读写指针。另外,根据严格别名说的,
char *可修改任何类型的数据。所以,我认为给
char *添加restrict,可防止【写指针写入数据后,编译器认为所有指针的数据缓存都失效不能用了,需要重新读取】。不知这个想法对不对
@老虎会游泳,我在给
SQLite写流式解析 csv 的小插件,想只用一个缓冲区存储:数据块、某一行解析好的CSV数据。比如,读取 4K 数据,然后边解析,边往这个缓冲区开头写入。
由于 CSV 数据解析完不会需要更多内存来存储,只会由于转义变得需要更少内存,所以不会发生写指针超出读指针问题。
所以,我在想写指针能不能加
restrict?加了有没有用?读指针需要加restrict吗?
@老虎会游泳,另外,我这篇帖子,主要是想讨论
restrict的(因为我已经认下严格别名了)。。我刚才看了看你一开始的其他回复。
我认为,根据 cppreference 对
restrict的叙述,应该是允许有其他别名的。只要保证:通过
restrict修饰的指针写入某个对象后,不再使用其他别名访问这个对象,即可?
@老虎会游泳,关于联合体,应该只有 C 能用,C++ 不能:
联合体的大小仅足以保有其最大的数据成员。其他数据成员在该最大成员的一部分相同的字节分配。分配的细节是实现定义的,且读取并非最近写入的联合体成员是未定义行为。许多编译器以非标准语言扩展实现读取联合体的不活跃成员的能力。
@老虎会游泳,诶,好像只是访问时 UB 噢,转换指针类型应该没问题?
@老虎会游泳,比如,
(long *)&y,编译器认为结果是NULL。。。
@老虎会游泳,
( long * ) &y这个是左值吗?解引用后,类型是long,不是字符类型,与float也不是兼容类型,所以应该是未定义行为。我 C/C++ 写得不多,现在看到那篇文章,就更怕编译器没能正确实现 UB 了。。
@老虎会游泳,我没能力修改
gcc,所以就认了。要么加-fno-strict-aliasing,要么用memcpy,来防止结果出错。但这还会影响到性能低下问题(特别是修改了
char *后,编译器会认为一大堆对象有可能被修改了,所以缓存失效,需要重新读取),所以我要搞懂restrict
@老虎会游泳,cppreference 说,这是 UB:
@老虎会游泳,按照标准,可能根本不会发生解引用指向float值的long指针,因为可能已经被优化掉了。。也就没有你后面说的浮点定义如何如何……
