☆─────────────────────────────────────☆
fangniuwawa (兰州放牛) 于 (Wed Oct 5 23:44:09 2022) 提到:
谢谢!
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Thu Oct 6 07:18:55 2022) 提到:
's'在C里面是int,在cpp里面是char
https://stackoverflow.com/questions/2172943/size-of-character-a-in-c-c
汇编和C里面经常将4个字符一起作为4字节的整数来操作,比如'1gaT'的值是0x31676154, 在内存里面是Tag1(little-endian),四个字符。
Windows内核驱动里面:
ExAllocatePoolWithTag(NonPagedPool,256, '1gaT');
☆─────────────────────────────────────☆
moneybox (乐乐) 于 (Thu Oct 6 11:11:54 2022) 提到:
没看懂,'s'不是1个字节吗
【 在 z16166 的大作中提到: 】
: 's'在C里面是int,在cpp里面是char
:
https://stackoverflow.com/questions/2172943/size-of-character-a-in-c-c: 汇编和C里面经常将4个字符一起作为4字节的整数来操作,比如'1gaT'的值是0x31676154, 在内存里面是Tag1(little-endian),四个字符。
: ...................
☆─────────────────────────────────────☆
flw (帅五进九) 于 (Thu Oct 6 12:21:30 2022) 提到:
当整数用了。
C 是弱类型,不要这么计较。
编译器说什么就是什么吧。
【 在 moneybox 的大作中提到: 】
: 没看懂,'s'不是1个字节吗
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Thu Oct 6 12:23:33 2022) 提到:
pure C里面,字面量's'是int类型的,怎么会一个字节呢?当然是4字节啦(int是4字节时)
你看C的库函数tolower()、toupper()的参数类型都是int的
在C++里,下面只有x1是char类型,x2/x3/x4都是int类型。可以在调试器中看到类型。
const auto x4 = '1gaT';
const auto x3 = 'gaT';
const auto x2 = 'aT';
const auto x1 = '1';
【 在 moneybox 的大作中提到: 】
: 没看懂,'s'不是1个字节吗
:
☆─────────────────────────────────────☆
robertrue (正宗robert) 于 (Thu Oct 6 13:58:01 2022) 提到:
sizeof('s')等价于sizeof(int),因为底层系统内部默认用int来存储's'这个字符,也就是4个字节。
如果写成下面这样:
char c = 's';
sizeof(c)的结果就是1。
【 在 fangniuwawa 的大作中提到: 】
: 谢谢!
☆─────────────────────────────────────☆
cjon (囧) 于 (Thu Oct 6 23:11:39 2022) 提到:
x2, x3, x4不都是string吗?c++里面的sizeof是咋个把它们转换成int的啊?
【 在 z16166 的大作中提到: 】
: pure C里面,字面量's'是int类型的,怎么会一个字节呢?当然是4字节啦(int是4字节时)
: 你看C的库函数tolower()、toupper()的参数类型都是int的
: 在C++里,下面只有x1是char类型,x2/x3/x4都是int类型。可以在调试器中看到类型。
: ...................
☆─────────────────────────────────────☆
smthwang00 (smthwang) 于 (Thu Oct 6 23:47:53 2022) 提到:
看看编译选项是不是按4字节对齐
【 在 fangniuwawa 的大作中提到: 】
:谢谢!
- 来自 水木社区APP v3.5.6
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Fri Oct 7 11:01:30 2022) 提到:
双引号才是string。单引号,就是int.
sizeof是老老实实地求某个变量或者常量的尺寸,没有任何转换的。
【 在 cjon 的大作中提到: 】
: x2, x3, x4不都是string吗?c++里面的sizeof是咋个把它们转换成int的啊?
☆─────────────────────────────────────☆
moneybox (乐乐) 于 (Fri Oct 7 12:02:53 2022) 提到:
那sizeof('abcdefg')尺寸是多大?
【 在 z16166 的大作中提到: 】
: 双引号才是string。单引号,就是int.
: sizeof是老老实实地求某个变量或者常量的尺寸,没有任何转换的。
:
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Fri Oct 7 12:32:03 2022) 提到:
这种问题,都不用问别人,自己输入到IDE里面编译、调试一下试试就知道了
学coding,就是要在编译器里多try(反正普通的操作是不会把电脑try坏的),这是我上第一堂计算机课时,我的老师在课堂上告知大家的。
你的这个问题我已经try过了,而且符合预期,但我不会直接提供答案。看看你try的结果是啥。
【 在 moneybox 的大作中提到: 】
: 那sizeof('abcdefg')尺寸是多大?
☆─────────────────────────────────────☆
milksea (肥了,又肥了 >>>_<<<) 于 (Fri Oct 7 17:20:12 2022) 提到:
标准和实现是两回事。有多个字符的字符字面量按规定必须是int类型,值则由实现确定。有些东西只靠试写不出跨平台代码,比如int的大小。
【 在 z16166 的大作中提到: 】
: 这种问题,都不用问别人,自己输入到IDE里面编译、调试一下试试就知道了
:
: 学coding,就是要在编译器里多try(反正普通的操作是不会把电脑try坏的),这是我上第一堂计算机课时,我的老师在课堂上告知大家的。
: ...................
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Fri Oct 7 18:29:28 2022) 提到:
分阶段,有的人还没到要写跨平台代码的阶段
而且搞跨平台代码的话,最开始也是要在不同的目标平台上try一遍来积累感性认识的
即使不知道标准怎么规定的,只要能让代码在要支持的编译器和平台上能正确工作,也是可以满足项目的阶段要求的。一般人可能也是发现代码在某些平台上不能正常工作,才会去看标准是怎么规定的。人的认知规律是特殊 -> 一般 -> 特殊
【 在 milksea 的大作中提到: 】
: 标准和实现是两回事。有多个字符的字符字面量按规定必须是int类型,值则由实现确定。有些东西只靠试写不出跨平台代码,比如int的大小。
☆─────────────────────────────────────☆
cjon (囧) 于 (Fri Oct 7 21:46:22 2022) 提到:
那'1gaT'是怎样转换成int的呢?
【 在 z16166 的大作中提到: 】
: 双引号才是string。单引号,就是int.
: sizeof是老老实实地求某个变量或者常量的尺寸,没有任何转换的。
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Fri Oct 7 22:05:40 2022) 提到:
'1gaT' == 0x31676154。0x31, 0x67, 0x61, 0x54就是四个字符的ASCII码,前面的字符成为高字节。
【 在 cjon 的大作中提到: 】
: 那'1gaT'是怎样转换成int的呢?
☆─────────────────────────────────────☆
cjon (囧) 于 (Fri Oct 7 22:10:09 2022) 提到:
编译器还有这个骚操作?真没想到。谢谢指点。
另:让我想起来二十多年前用 Hex Workshop 改游戏的存盘文件。
【 在 z16166 的大作中提到: 】
: '1gaT' == 0x31676154。0x31, 0x67, 0x61, 0x54就是四个字符的ASCII码,前面的字符成为高字节。
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Fri Oct 7 22:46:28 2022) 提到:
多字符的char literal不是标准的(编译器实现相关的),就是楼上milksea所说的
【 在 cjon 的大作中提到: 】
: 编译器还有这个骚操作?真没想到。谢谢指点。
: 另:让我想起来二十多年前用 Hex Workshop 改游戏的存盘文件。
☆─────────────────────────────────────☆
cjon (囧) 于 (Fri Oct 7 22:53:18 2022) 提到:
明白啦,非常感谢。
【 在 z16166 的大作中提到: 】
: 多字符的char literal不是标准的(编译器实现相关的),就是楼上milksea所说的
☆─────────────────────────────────────☆
milksea (肥了,又肥了 >>>_<<<) 于 (Sat Oct 8 07:06:14 2022) 提到:
只这么想遇到ub就完蛋
【 在 z16166 的大作中提到: 】
: 分阶段,有的人还没到要写跨平台代码的阶段
:
: 而且搞跨平台代码的话,最开始也是要在不同的目标平台上try一遍来积累感性认识的
: ...................
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Sat Oct 8 09:28:34 2022) 提到:
哈哈,我又没说只有try这一种学习方法
可以去自己啃语言标准文档中的章节,
也可以去读别人啃完标准文档后提前写明了哪些地方有坑的书,
但纸上得来的东西,还得自己躬行,也就是还得try
【 在 milksea 的大作中提到: 】
: 只这么想遇到ub就完蛋
☆─────────────────────────────────────☆
haha103 (haha103) 于 (Sat Oct 8 10:18:22 2022) 提到:
try的时候还是要明白自己try的是实现不是标准就行了。
下面这个代码估计不少人不知道UB在哪里(导致有些编译器输出结果是0,有些是65535),哈哈
#include <iostream>
#include <cstdint>
using namespace std;
uint64_t g_x = 0;
struct myclass {
myclass(uint32_t x) { _data = x;}
uint16_t hi() const { return (uint16_t)((_data & 0xFFFF0000) >> 16); }
uint16_t lo() const { return (uint16_t)((_data & 0xFFFF)); }
uint32_t _data;
};
__attribute__((noinline)) void dummy(uint32_t x1, uint32_t x2) {
g_x = x1 + x2;
}
__attribute__((noinline)) int func(uint32_t a, uint32_t b) {
const uint32_t x1 = myclass(a).hi() * myclass(b).lo();
const uint32_t x2 = x1 + myclass(a).lo() * myclass(b).hi();
dummy(x1, x2);
int ret = 0;
if ( x2 < x1 ) {
ret = 0x10000;
}
return ret;
}
int main(int argc, char** argv) {
cout << func(4294967295, 4294917296) << endl;
return 0;
}
【 在 z16166 的大作中提到: 】
: 哈哈,我又没说只有try这一种学习方法
: 可以去自己啃语言标准文档中的章节,
: 也可以去读别人啃完标准文档后提前写明了哪些地方有坑的书,
: ...................
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Sat Oct 8 11:51:15 2022) 提到:
搜了一下,integer promotion + signed integer overflow,这二者一结合,简直是bug制造机吧。但码农应该在预估到乘法可能溢出时要显式做整数的宽度提升转换。
原帖和引用的帖子,值得一读。不过并未说明为什么老版本的g++和新版本的g++搞出来的值不一样,新版本的g++算是fix了老版本一直存在的bug?
【 在 haha103 的大作中提到: 】
: try的时候还是要明白自己try的是实现不是标准就行了。
: 下面这个代码估计不少人不知道UB在哪里(导致有些编译器输出结果是0,有些是65535),哈哈
: #include <iostream>
: ...................
☆─────────────────────────────────────☆
haha103 (haha103) 于 (Sat Oct 8 11:57:03 2022) 提到:
UB嘛,任何结果都不能怪编译器撒,哈哈
【 在 z16166 的大作中提到: 】
: 搜了一下,integer promotion + signed integer overflow,这二者一结合,简直是bug制造机吧。但码农应该在预估到乘法可能溢出时要显式做整数的宽度提升转换。
: 原帖和引用的帖子,值得一读。不过并未说明为什么老版本的g++和新版本的g++搞出来的值不一样,新版本的g++算是fix了老版本一直存在的bug?
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Sat Oct 8 12:00:52 2022) 提到:
那就怪谁定的这个自动提升规则
integer promotion提升为signed int,然后signed integer overflow,完美的二连击
【 在 haha103 的大作中提到: 】
: UB嘛,任何结果都不能怪编译器撒,哈哈
☆─────────────────────────────────────☆
haha103 (haha103) 于 (Sat Oct 8 12:04:40 2022) 提到:
其实主要是这个integer promotion比较坑爹,signed overflow是UB很多人写代码的时候都会注意
如果提升之后也是unsigned就没这些问题了
【 在 z16166 的大作中提到: 】
: 那就怪谁定的这个自动提升规则
: integer promotion提升为signed int,然后signed integer overflow,完美的二连击
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Sat Oct 8 12:55:38 2022) 提到:
谢谢分享
【 在 haha103 的大作中提到: 】
: 其实主要是这个integer promotion比较坑爹,signed overflow是UB很多人写代码的时候都会注意
: 如果提升之后也是unsigned就没这些问题了
☆─────────────────────────────────────☆
gameplayer (*.*) 于 (Sat Oct 8 14:30:43 2022) 提到:
确实没看出来...这要遇到肯定掉坑里,爬都爬不出来...
实际试了下,g++ 12.2.0, O0和O1下输出65536,O2输出0,clang++只有O0输出65536,
O1和O2都输出0
【 在 haha103 的大作中提到: 】
: try的时候还是要明白自己try的是实现不是标准就行了。
: 下面这个代码估计不少人不知道UB在哪里(导致有些编译器输出结果是0,有些是65535),哈哈
: #include <iostream>
: ...................
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Sat Oct 8 16:02:17 2022) 提到:
参考。需要自己思考的,可以先不看下面的内容:
https://stackoverflow.com/questions/55379684/strange-behavior-between-g-8-and-earlier-versions
https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
【 在 gameplayer 的大作中提到: 】
: 确实没看出来...这要遇到肯定掉坑里,爬都爬不出来...
: 实际试了下,g++ 12.2.0, O0和O1下输出65536,O2输出0,clang++只有O0输出65536,
: O1和O2都输出0
: ...................
☆─────────────────────────────────────☆
haha103 (haha103) 于 (Sat Oct 8 16:04:51 2022) 提到:
哈哈,翻到了我以前提的问
【 在 z16166 的大作中提到: 】
: 参考。需要自己思考的,可以先不看下面的内容:
:
https://stackoverflow.com/questions/55379684/strange-behavior-between-g-8-and-earlier-versions:
https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules: ...................
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Sat Oct 8 23:35:51 2022) 提到:
你这个知识点(或者说坑)也是try出来的,针对不同的编译器版本try之后发现不同点。
对一门复杂的语言,普通人没可能预先面面俱到地把各个知识点都学一下(可称为god模式或者先知模式,预知一切。即使先学了,没有实战,最后也多半会忘光),
更多地是先学一个初步框架,然后在使用中趟坑学习更多的小知识点。不过,貌似此乃废话
【 在 haha103 的大作中提到: 】
: 哈哈,翻到了我以前提的问
☆─────────────────────────────────────☆
haha103 (haha103) 于 (Sun Oct 9 08:22:40 2022) 提到:
所以我说try的时候要知道自己try的结果代表的是实现不是标准,然后知道实现和标准不能划等号 :)
【 在 z16166 的大作中提到: 】
: 你这个知识点(或者说坑)也是try出来的,针对不同的编译器版本try之后发现不同点。
: 对一门复杂的语言,普通人没可能预先面面俱到地把各个知识点都学一下(可称为god模式或者先知模式,预知一切。即使先学了,没有实战,最后也多半会忘光),
: 更多地是先学一个初步框架,然后在使用中趟坑学习更多的小知识点。不过,貌似此乃废话
: ...................
☆─────────────────────────────────────☆
fayewong (Dying In The Sun) 于 (Sun Oct 9 08:52:03 2022) 提到:
遇到big endian会哭
【 在 z16166 (Netguy) 的大作中提到: 】
: 多字符的char literal不是标准的(编译器实现相关的),就是楼上milksea所说的
:
: 【 在 cjon 的大作中提到: 】
: : 编译器还有这个骚操作?真没想到。谢谢指点。
☆─────────────────────────────────────☆
sqich (sqich) 于 (Sun Oct 9 09:02:44 2022) 提到:
可能是字节对其的问题。
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Sun Oct 9 14:21:28 2022) 提到:
你事先并不知道是什么原因,也就不可能提前知道这个问题是“标准中明确规定了不是实现相关的”,还是“标准中明确说了编译器的实现者可以自行决定”
所以也不可能一直是god模式在学东西,标准怎么定的都事先搞清楚了,肯定会有两眼一抹黑、摸着石头过河的时候。
【 在 haha103 的大作中提到: 】
: 所以我说try的时候要知道自己try的结果代表的是实现不是标准,然后知道实现和标准不能划等号 :)
☆─────────────────────────────────────☆
z16166 (Netguy) 于 (Sun Oct 9 14:53:42 2022) 提到:
只要事先知道要用的这个特性是实现相关的就好办(查一下标准应该能做到这点),比如加个assert('1gaT' == 0x31676154)或者static_assert()
当然,能避免使用实现相关的特性,自然是要尽量避免
在汇编或者windows driver里用'1gaT',这两个本身就是不用考虑可移植性的场景
【 在 fayewong 的大作中提到: 】
: 遇到big endian会哭