V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
nikoo
V2EX  ›  问与答

请不要测试直接回答 echo "a" > a.txt 该文件大小多少字节?

  •  
  •   nikoo · 2017-06-22 12:29:31 +08:00 · 6688 次点击
    这是一个创建于 2748 天前的主题,其中的信息可能已经有所发展或是发生改变。
    感觉有点意外,两个问题:
    1、这是为什么?
    2、这合理吗?
    75 条回复    2017-07-03 23:21:22 +08:00
    zwpaper
        1
    zwpaper  
       2017-06-22 12:32:50 +08:00   ❤️ 1
    2 字节,一个 a,一个换行。

    我去测试一下来回复
    zwpaper
        2
    zwpaper  
       2017-06-22 12:34:58 +08:00
    就是 2 字节
    1. "a" + "换行" = 2
    2. 合理
    nikoo
        3
    nikoo  
    OP
       2017-06-22 12:35:32 +08:00
    @zwpaper 是的,今天在生产服直接编辑文件就因为这个末尾的\n 导致了 BUG,vim 编辑器也有这个“问题”
    lululau
        4
    lululau  
       2017-06-22 12:35:33 +08:00 via iPhone
    不一定,看当前环境的字符编码是什么吧
    ldbC5uTBj11yaeh5
        5
    ldbC5uTBj11yaeh5  
       2017-06-22 12:36:14 +08:00   ❤️ 4
    这个问题太弱智了。我来提供一个巨坑人的题目

    sizeof('A') 和 sizeof("A") 谁大?

    我见过编程十年的经验的老手都被套路了。
    nikoo
        6
    nikoo  
    OP
       2017-06-22 12:37:27 +08:00
    按理说 echo 单一字符不应该强制加换行在末尾吧。
    ETiV
        7
    ETiV  
       2017-06-22 12:39:11 +08:00 via iPhone
    C 里 sizeof 一个是 char,一个是 char*
    ldbC5uTBj11yaeh5
        8
    ldbC5uTBj11yaeh5  
       2017-06-22 12:40:12 +08:00
    sizeof 这道题我最喜欢去套路那些"熟悉 C/C++"的程序员,鲜有能够滴水不漏完完整整说出来龙去脉的哥们。
    40huo
        9
    40huo  
       2017-06-22 12:40:34 +08:00 via Android
    为什么 windows 下是 6 字节。。
    we000
        10
    we000  
       2017-06-22 12:41:37 +08:00   ❤️ 1
    @nikoo 你说的 Vim 的问题, 可能需要用 vim -b 以 binary 形式打开
    ldbC5uTBj11yaeh5
        11
    ldbC5uTBj11yaeh5  
       2017-06-22 12:41:38 +08:00
    @ETiV 哥们,你也被套路了。这个题目埋了不少雷。C vs C++, 32bit vs LP64 等等呢。
    40huo
        12
    40huo  
       2017-06-22 12:42:25 +08:00 via Android
    啊,win 下还会把引号写进去。。
    laoyur
        13
    laoyur  
       2017-06-22 12:44:04 +08:00
    echo -n "a"
    echo "a"
    在终端敲一下试试
    xss
        14
    xss  
       2017-06-22 12:44:23 +08:00   ❤️ 1
    请使用 echo -ne 'a' > a.txt
    不熟指令, echo 不背这锅
    lfk0000
        15
    lfk0000  
       2017-06-22 12:44:45 +08:00 via Android
    好像换行还分 3 种写法?
    想起茴香豆了...
    wevsty
        16
    wevsty  
       2017-06-22 12:46:44 +08:00
    @ETiV
    @jigloo
    "a"是被当作字符数组处理的,结尾有 /0。
    直接 sizeof("a")是求了整个字符数组包括 /0 的大小,所以实际上是 2 个字节
    sizeof(‘ a ’)是 1 应该没有什么争议。
    当然,这都是不考虑平台,编码的情况下,如果加上这些,还有些变数。
    ldbC5uTBj11yaeh5
        17
    ldbC5uTBj11yaeh5  
       2017-06-22 12:47:57 +08:00
    sizeof(‘ a ’)是 1 应该没有什么争议。

    呵呵,你试过了吗?
    Tink
        18
    Tink  
       2017-06-22 12:49:00 +08:00 via iPhone
    跟操作系统有关
    ldbC5uTBj11yaeh5
        19
    ldbC5uTBj11yaeh5  
       2017-06-22 12:50:24 +08:00   ❤️ 2
    一般来说,当被套路的程序员意识在 c 里面 sizeof('A') 是 sizeof(int), 而在 c++ 里面是 sizeof(char) 的时候。

    我都会追问一句,“为什么这么设计?” 能答上来的话,我就不和对方在 c/c++ 基础知识上纠缠了。蛤蛤
    lcdtyph
        20
    lcdtyph  
       2017-06-22 12:58:25 +08:00
    @jigloo #19 我只知道这是两个语言标准规定的字面值类型不同导致的……至于为什么这么设计,还请赐教
    QAPTEAWH
        21
    QAPTEAWH  
       2017-06-22 13:02:27 +08:00
    然后这个文件占 4K 大小?
    ldbC5uTBj11yaeh5
        22
    ldbC5uTBj11yaeh5  
       2017-06-22 13:03:40 +08:00   ❤️ 14
    @lcdtyph c 如此设计的原因和 fgetc 为什么返回值是 int 相同。
    c++ 又改成 char 的原因是因为要做操作符重载,不然 cout << 'A' 输出数字就尴尬了。
    qichunren
        23
    qichunren  
       2017-06-22 13:04:03 +08:00
    sizeof(‘ a ’)是 1,我试过了,g++, 64 位。
    ldbC5uTBj11yaeh5
        24
    ldbC5uTBj11yaeh5  
       2017-06-22 13:05:05 +08:00
    @qichunren 大兄弟,回帖要看帖。
    wevsty
        25
    wevsty  
       2017-06-22 13:06:20 +08:00
    @jigloo
    查了一下看来我还是被套路了~

    @lcdtyph
    估计这么设计是因为 C 里面更多的是从底层数据考虑吧,字符本身也是也是数字,只是认为的规定了数字这么解释代表了这个意思。
    holyghost
        26
    holyghost  
       2017-06-22 13:07:09 +08:00
    @jigloo

    SO 上有一些关注这个的讨论:
    https://stackoverflow.com/a/3672617
    https://stackoverflow.com/a/433988

    我猜大意是 C 中的 char 会被当作 int 来处理,C++中处理得更加严谨了一些。
    不知道是否靠谱?
    yws112358
        27
    yws112358  
       2017-06-22 13:57:20 +08:00 via iPhone   ❤️ 1
    占用磁盘空间和文件系统有关 最小 512 字节 实际大小看情况
    after1990s
        28
    after1990s  
       2017-06-22 14:04:23 +08:00
    sizeof 其实是个运算符,可以被重载的。所以 sizeof('a')不一定返回 1.
    lcdtyph
        29
    lcdtyph  
       2017-06-22 14:08:00 +08:00
    @after1990s #28 不是所有运算符都能被重载的,而且 sizeof 不是严格的运算符。
    after1990s
        30
    after1990s  
       2017-06-22 14:08:57 +08:00
    @after1990s 好像并不可以。。。
    jason19659
        31
    jason19659  
       2017-06-22 14:33:50 +08:00
    alias cat echo
    crab
        32
    crab  
       2017-06-22 14:49:38 +08:00
    @40huo 引号,还有引号后的空格+回车+换行
    0asis
        33
    0asis  
       2017-06-22 15:08:16 +08:00
    x64
    gcc 下,int *a = 3; sizeof(a) == 8;sizeof(1)==4, sizeof('a') == 4, sizeof("a") == 2
    g++下,sizeof(1) == 4, sizeof('a')==1, sizeof("a") == 2
    jixiangqd
        34
    jixiangqd  
       2017-06-22 15:15:38 +08:00
    ```bash
    echo -n "a"
    ```
    cxbig
        35
    cxbig  
       2017-06-22 15:53:58 +08:00 via iPhone
    echo 默认带回车
    1. echo -n 'a'
    2. printf 'a'
    ldbC5uTBj11yaeh5
        36
    ldbC5uTBj11yaeh5  
       2017-06-22 16:02:09 +08:00   ❤️ 1
    @0asis 嗯,这个就是这个问题蕴含的另一个套路了,一般如果答题者试图像这样过关的话,接下来是 LP64, ILP64, LLP64 的套路问题等着。

    所以我才说,这个问题要答的“滴水不漏”颇为坑人。
    zhangxaochen
        37
    zhangxaochen  
       2017-06-22 16:05:40 +08:00
    @0asis @jigloo 请教,为啥 sizeof("a") ==2 呢? 本以为 "a" 给粗的是指针地址,以为 == 4 来着。。
    0asis
        38
    0asis  
       2017-06-22 16:26:38 +08:00
    @zhangxaochen #37 可能是 a\0 两个字节?其实我也一直以为对“”取 sizeof 会得到一个 char 的指针的大小
    0asis
        39
    0asis  
       2017-06-22 16:29:44 +08:00
    @0asis #38 不对不对,sizeof 应该是不会包括\0 的,我也迷了
    0asis
        40
    0asis  
       2017-06-22 16:43:09 +08:00
    @0asis 似乎就是#38 的想法- -,尴尬了
    hsmocc
        41
    hsmocc  
       2017-06-22 17:17:53 +08:00 via iPhone
    不懂 lp64 之类的、感觉 c 不是强类型的语言所以编译器把'a' 当作 int 处理,而 c++这种强类型的是 char 就是 char
    wwqgtxx
        42
    wwqgtxx  
       2017-06-22 17:18:15 +08:00
    @0asis
    const char *c = "a";
    std::cout<<sizeof(c)<<std::endl;
    std::cout<<sizeof("a")<<std::endl;

    >8
    >2

    个人觉得这个地方应该是编译器直接求值了
    canfoderiskii
        43
    canfoderiskii  
       2017-06-22 17:28:41 +08:00 via Android
    @0asis sizeof 用于字面字符串相当于用于编译期确定长度的数组
    tghgffdgd
        44
    tghgffdgd  
       2017-06-22 17:46:30 +08:00
    虽然认为是 2 个字节,但是实际上可以 2 个字节,也可以 7 个字节,也可以 8 个字节,跟环境有关系啊
    canfoderiskii
        45
    canfoderiskii  
       2017-06-22 17:49:06 +08:00 via Android
    @jigloo 查了 c11 标准,标准里面并没有直接提到 sizeof 用于字面字符串的情形。
    对于字面字符串,标准 6.4.5 string literal 一节里面有这么一句: The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence.

    所以我认为,字面字符串的类型是数组,sizeof 返回值就是数组长度
    lululau
        46
    lululau  
       2017-06-22 17:52:59 +08:00
    mkdir tmp
    cd tmp
    rm -rf *
    echo > a
    echo > b

    command ls -l | wc -l # => 答案是几?
    veelog
        47
    veelog  
       2017-06-22 19:10:52 +08:00 via iPhone
    char s[]="A";
    sizeof("A") == sizeof(s)
    veelog
        48
    veelog  
       2017-06-22 19:11:45 +08:00 via iPhone
    echo -n "" >a.txt
    bumz
        49
    bumz  
       2017-06-22 19:28:54 +08:00
    @canfoderiskii #45 不对的。数组长度是 sizeof(array) / sizeof(array[0])。只是由于 sizeof(char) 是 1,分母就没了。
    bumz
        50
    bumz  
       2017-06-22 19:35:01 +08:00
    @jigloo #5 char 'A' 会被自动变成 int,因此前者是 4 字节; string literal "A" 是 {'A', '\0'} 的语法糖,占用两字节,因此后者是 2 字节。

    相关知识点:char 型的值会自动变 int 型的值,因此 char literal 直接是一个 int,以免多余的类型转换; string literal 是数组的语法糖; sizeof(数组)/sizeof(数组第一个元素)。
    bumz
        51
    bumz  
       2017-06-22 19:35:16 +08:00
    数组长度 = sizeof(数组)/sizeof(数组第一个元素)。
    ldbC5uTBj11yaeh5
        52
    ldbC5uTBj11yaeh5  
       2017-06-22 19:37:45 +08:00
    @bumz 大兄弟,还是那句话,回帖要看帖。
    menc
        53
    menc  
       2017-06-22 20:08:14 +08:00   ❤️ 9
    这个帖子贼厉害,一个帖子下面讨论两个不同的话题且互不干涉,堪称精分现场典范。
    huluhulu
        54
    huluhulu  
       2017-06-22 21:35:01 +08:00
    文件大小=磁盘一簇的大小,NTFS 或者 fat32 默认是 4k
    你也可以更大
    mozutaba
        55
    mozutaba  
       2017-06-22 21:44:05 +08:00   ❤️ 1
    取决于文件簇
    kingddc314
        56
    kingddc314  
       2017-06-22 22:27:29 +08:00   ❤️ 1
    前面两个黑白头像,还以为网有问题
    canfoderiskii
        57
    canfoderiskii  
       2017-06-22 23:05:27 +08:00 via Android
    @bumz 我表述问题而已。sizeof 数组就是数组字节长度
    mingyun
        58
    mingyun  
       2017-06-22 23:19:21 +08:00
    想起了那个命令行生成 md5 不同的问题,就是因为换行
    extreme
        59
    extreme  
       2017-06-22 23:49:52 +08:00
    @wwqgtxx You are right

    // sizeof.cpp
    #include <iostream>

    void printSizeof() {
    int sizeofValue = sizeof("a");
    // std::cout<<sizeofValue<<std::endl;
    }

    bash - :~ # g++ -c -O0 sizeof.cpp
    bash - :~ # objdump -S sizeof.o | less
    ...
    0000000000000000 <_Z11printSizeofv>:
    0: 55 push %rbp
    1: 48 89 e5 mov %rsp,%rbp
    4: 48 83 ec 10 sub $0x10,%rsp # 给 int a 分配储存空间,0x10 大概是为了对齐
    8: c7 45 fc 02 00 00 00 movl $0x2,-0x4(%rbp) # 把值 0x2 存入变量 a 中
    f: 90 nop
    10: 48 83 c4 10 add $0x10,%rsp
    14: 5d pop %rbp
    15: c3 retq
    ...
    msg7086
        60
    msg7086  
       2017-06-23 00:56:41 +08:00
    @huluhulu 那不是文件大小,那是文件占用大小。
    文件也不一定要占用整个簇,比如小文件就可以直接储存在 MFT 表项中而不用另开一簇。
    phoebuss
        61
    phoebuss  
       2017-06-23 05:37:02 +08:00 via Android
    应该用 echo -n
    fovecifer
        62
    fovecifer  
       2017-06-23 09:54:11 +08:00
    请用 echo -n
    yuchting
        63
    yuchting  
       2017-06-23 11:15:35 +08:00
    楼上 sizeof 跑题的那位,这个运算符和编译器(预处理器)有很大关系,有些编译器说不定给出警告甚至错误,在使用 C 和 C++的时候,尽量少使用 sizeof,多用宏直接写死,不写 C++6 年的大叔的忠告。
    intsilence
        64
    intsilence  
       2017-06-23 11:29:48 +08:00
    用 echo -n 或者 printf 就好咯。
    ldbC5uTBj11yaeh5
        65
    ldbC5uTBj11yaeh5  
       2017-06-23 11:40:28 +08:00
    @yuchting 蛤蛤,被套路了以后,这转进真奇葩。。。
    ldbC5uTBj11yaeh5
        66
    ldbC5uTBj11yaeh5  
       2017-06-23 11:42:34 +08:00
    这道题是我数年前的原创,专门收拾这些嘴硬的自认为“熟悉 C/C++”的程序员。
    SoloCompany
        67
    SoloCompany  
       2017-06-23 12:19:12 +08:00
    man 一下就有结果的问题就不要意外了,多一个回车这种问题早就应该发现了,否则在一个 shell 里面连续的 echo 语句就会变成一团东西

    更大的坑应该是 echo -n 并不是总是有效,你 man 一下 BSD 的 echo 指令( MacOS )的说明,内置的 echo 命令是不支持 -n 的

    这个命令 sh -c ‘ echo -n a ’ 在 MacOS 下执行是输出 -n a 而不是 a

    所以最保险的方法还是应该使用 printf
    NoAnyLove
        68
    NoAnyLove  
       2017-07-02 02:28:53 +08:00
    @jigloo 请教一下,关于#19 楼的问题,#22 楼的说法是“ c 如此设计的原因和 fgetc 为什么返回值是 int 相同”。我查了一下,fgetc 的返回值是 int 的原因是为了区分返回值可能是-1 的情况,所以要将 char 升级到 int。但是为啥 C 语言中,sizeof 的情况下也要将其升级为 int 呢?
    panda1001
        69
    panda1001  
       2017-07-02 08:02:49 +08:00 via Android
    不指定操作平台和编译器
    owt5008137
        70
    owt5008137  
       2017-07-02 16:39:08 +08:00 via Android
    @NoAnyLove ch 爱人也能表示-1。 @jigloo 不过同样请教下 fgetc 和推断类型为 int 的原因。难道是因为没有重载而且要能表示 wchar_t ?
    NoAnyLove
        71
    NoAnyLove  
       2017-07-03 07:28:32 +08:00
    @owt5008137 “ ch 爱人也能表示-1 ”?这是啥意思?是不是哪个字打错了?
    owt5008137
        72
    owt5008137  
       2017-07-03 08:28:09 +08:00 via Android
    @NoAnyLove 打错了,char 也能表示-1。(T_T)
    NoAnyLove
        73
    NoAnyLove  
       2017-07-03 10:56:42 +08:00
    @owt5008137 那你怎么区分 EOF 和读取了 255 个字节的长度?
    owt5008137
        74
    owt5008137  
       2017-07-03 20:15:29 +08:00 via Android
    @NoAnyLove 啊。我和你说的不是同一个层面的意思。我说的能表示是说 char 类型可以赋值-1。如果说是范围问题,那确实是不能表示
    NoAnyLove
        75
    NoAnyLove  
       2017-07-03 23:21:22 +08:00
    @owt5008137。。。。。。。我在#68 楼说的就是“为了区分返回值可能是-1 的情况” (破涕为笑)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1006 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 22:28 · PVG 06:28 · LAX 14:28 · JFK 17:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.