代码之家  ›  专栏  ›  技术社区  ›  cdpp

C中的“str”-“str”是如何工作的?它们是如何储存的?

  •  -1
  • cdpp  · 技术社区  · 8 年前

    免责声明:此问题询问如何 "str literal" + "str literal" 作品

    为什么 'a' + 'b' '9' - '0' = 9 (“character”+“character”)起作用:


    问题:

    对于每一个更熟悉C的人,感谢阅读

    (用clang编译,标准=C11)

    例子:

    __FILE__ 没有its ".c" 扩展)

    printf("%s\n", __FILE__); 退货 filename.c

    printf("%.*s\n", (int)(".c" - __FILE__), __FILE__); 退货 filename

    1.C如何将字符串/字符串文字转换为int?是否忽略空白?

    • 一个 (int)"string"

    另一个例子:

    (int)("word" - "rd") = 6273
    (int)("rd" - "word") = -6273
    (int)("word" - "  rd") = -5
    (int)("  rd" - "word") = -5
    

    为什么 (int)(".c" - __FILE__) 甚至工作?

    3. printf 以上功能是否实际工作?

    4.

    提前谢谢大家!



    无关猜测:

    1. (int)(.c“-\uu FILE\uuuu) 甚至工作?

    猜测其

      some value of (first?) pointer to ".c" 
    - some value of (first?) pointer to __FILE__ string literal 
    

    它的价值是什么 实际代表?

    • (int)(.c“-\uu FILE\uuuu) 甚至工作?

    idk但这里有另一个例子:

    printf("%i", (int)".c");
    printf("%i", (int)__FILE__);
    printf("%i", (int)(".c" - __FILE__));
    printf("%i", (int)(__FILE__ - ".c"));
    printf("%./*i", (int)(".c" - __FILE__), (int)__FILE__);
    printf("%./*i", (int)(".c" - __FILE__), (int)("c" - __FILE__));
    
    output
    ---------------------
    (int) ".c"= 4357629
    (int) __FILE__= 4357620
    (int) (".c" - __FILE__) : 9
    (int) (__FILE__ - ".c"): -9
    (int with precision specified) __FILE__ : 004357620
    (int with precision specified) (".c" - __FILE__): 000000009 
    $
    

    打印F 实际工作?

    假设是这样,可能:

    printf("%.*s",(int)(".c" - __FILE__), __FILE__)
        width = (int)(".c" - __FILE__)   
        specifier/str = __FILE__
    

    打印F 打印输出 __文件__ 作为一串宽度 (".c" - __FILE__) (少于两个字符)

    2 回复  |  直到 8 年前
        1
  •  1
  •   Clifford    8 年前

    在你的例子中发生了三件事。

    首先,在C语言中,指针算术规则是这样的:两个指针可以相减以产生 在两个指针之间。例如:

    char test[2] ;
    char* t1 = &test[0] ;
    char* t2 = &test[1] ;
    ptrdiff_t d = t2 - t1  ; // d == 1
    

    哪里 ptrdiff_t 是一个整数类型,能够容纳 任何 两个指针。铸造至 int 可能是错误的,如32位 整数 它将仅跨越2Gb,因此不太可能出现错误。

    第二件事是字符串文字,例如 "word" 在表达式中使用时是 指针 到字符串内容。

    第三件事是你的链接器已经执行了 重复字符串消除 . 它彻底搜索了代码中相同的字符串文字,并将其替换为单个指针。这部分观察结果取决于实现,可能不适用于所有工具链,甚至不适用于具有不同编译器/链接器设置的同一工具链。

    __FILE__ 是一个字符串文字,包含实例化源文件的名称。在示例中:

    (int)(".c" - __FILE__)
    

    __文件__ == "filename.c" 链接器会找到副本 ".c" 在此范围内(必须在末尾,因为nul终止符必须匹配)。因此,两个指针值之间的差值为8(长度为 "filename" ). 因此声明:

    printf("%.*s\n", (int)(".c" - __FILE__), __FILE__);
    

    打印字符串的前8个字符 “文件名.c” 这就是 “文件名” .

    更复杂的事情正在发生:

    (int)("word" - "rd") = 6273
    (int)("rd" - "word") = -6273
    (int)("word" - "  rd") = -5
    (int)("  rd" - "word") = -5 
    

    在第一种和第二种情况下,您可能会从第一种 __文件__ 示例预期分别为-2和2,但是可能会出现这种情况,但在这种情况下,链接器可能已匹配 "rd" 随着 " rd" 字符串,而不是以结尾 “文字” . 链接器行为由实现定义且不确定。结果可能会有所不同,例如,如果删除第三个和第四个表达式,使字符串文字不再存在。可以引用来自完全不同的链接模块的字符串。

    关键是,您不能依赖于这种完全未定义/实现的行为(字符串消除,即指针算术和文字字符串指针行为定义良好)。作为链接器行为的检查,它很有趣,但作为编程技术,它并不有用。

        2
  •  1
  •   Tom Karzes    8 年前

    字符串(带双引号),例如。 "abc" ,转换为指针 当用作表达式时 . 如果将整数添加到指针,则会得到一个新指针。如果减去两个兼容的指针,则得到一个整数。

    字符(带单引号),例如。 'x' ,只是一个整数。你可以加,减,等等,就像任何其他整数一样。

    __FILE__ 扩展为字符串,因此 ".c" - __FILE__ 是减去两个指针所得的整数。

    如果将指针强制转换为整数,则得到一个整数。

    请记住,一些涉及指针的表达式可能没有很好的定义,但数据类型是。

    推荐文章