在 C 程序中使用 Struct 和 strlen 进行数学运算

Math with Struct and strlen in C program

谁能解释一下下面的代码片段:strlen(S -> S + 5)

完整的代码在下面,但是如果我用其他数字替换 +5 (-1,0,1,2,3...) 输出有一个我无法辨别的模式,因此我想问这个值是如何确定的。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    struct S {
        char *S;// = 1 BYTE EACH
    };

    int main(void) {
        struct S *S = (struct S *) malloc(sizeof(struct S));//pointer created to Structure S with memory allocated of associated size.
        S -> S = "123[=10=]""45678";// Pointer S now pointing to the value S which is holding "123[=10=]""45678" Which has a stop character [=10=]
        printf("%s\n", S->S);// The pointer S points to the string S
        printf("%c\n\n", S -> S[6]);// gives the value, the character, in the   string at [] position
        printf("Length %d\n", strlen(S -> S)); // = 3 because the "[=10=] stop character stops the count (0,1,2,3)
        printf("Length + 5 = %d\n", strlen(S -> S+ 5)); // = total of 5


        printf("%d", strlen(S -> S + 5) + S -> S[3]);
        free(S);
        return 0;
    }

S -> S + 5 是字符串指针在结构内的偏移量(距离起始位置 5 个字符),因此该子字符串的长度会有所不同。 如果您使用 S -> S - 1 那么您已经超出了字符串的开头,任何事情都可能发生。

如果您确实想要 Length + 5(正如您的打印语句所建议的那样),那么您需要将 +5 移出括号 :)

printf("Length + 5 = %d\n", strlen(S -> S) + 5); // = total of 5

if I replace +5 with other numbers (-1,0,1,2,3...) the output has a pattern I cannot discern and therefore I am asking how the value is determined.

对于指针指向:

 S -> S = "123[=10=]""45678"

这些是 strlen 的结果:

    // reaching outside the string boundary, Undefined Behaviour
    strlen(S -> S-1)                    // UB: crash, 0 or 4

                                        // Equivalent to: 
    printf("%d\n", strlen(S -> S));     // 3 = strlen("123");
    printf("%d\n", strlen(S -> S+1));   // 2 = strlen("23");
    printf("%d\n", strlen(S -> S+2));   // 1 = strlen("3");
    printf("%d\n", strlen(S -> S+3));   // 0 = strlen("");
    printf("%d\n", strlen(S -> S+4));   // 5 = strlen("45678");
    printf("%d\n", strlen(S -> S+5));   // 4 = strlen("5678");

注:

size_t strlen ( const char * str );

Returns C 字符串的长度 str.

C 字符串的长度由终止符 null-character 决定。 C 字符串与字符串开头和 terminating null character 之间的字符数一样长(不包括终止空字符本身)。 terminating null character'[=20=]'

这里要理解的重要一点是

S->S = "123[=10=]""45678";

首先,->是指针的成员访问运算符。这里的诀窍是 这个:

"123[=11=]""45678"

在 C 中,当您将两个字符串文字写在一起时,它们会连接成一个。 例如

const char *txt = "Hello " "world";
puts(txt);

将打印 Hello world。这与做

是一样的
const char *txt = "Hello world";
puts(txt);

现在"123[=22=]""45678"正在使用字符串文字连接,并且还使用了一个技巧来存储 两个单独的字符串一次。字符串以 '[=23=]' 结尾,通常你不需要 使用字符串时需要明确使用 '[=23=]' 终止字节 文字,编译器会为你做,但你可以用它来存储多个 字符串一次。 S->S的记忆是这样的

index 0      1     2     3      4     5     6     7     8     9
      +-----+-----+-----+------+-----+-----+-----+-----+-----+------+
      | '1' | '2' | '3' | '[=14=]' | '4' | '5' | '6' | '7' | '8' | '[=14=]' |
      +-----+-----+-----+------+-----+-----+-----+-----+-----+------+

第二个要理解的重要事情是:

S -> S + 5

这相当于

&(S->S[5])

S->S + 5 是指针运算,就像常规运算一样 不同之处在于编译器会处理对象的大小。如果你有:

int arr[] = { 99, 11, 33, 55 };

而你想获取数组第二个元素1的地址,可以这样做: &(arr[1])。但是你也可以使用指针算法和等价物 语句将是 arr+1。编译器负责 int 的大小 当它添加偏移量时(即 1*sizeof(int))。

上面的代码同时使用了这两种东西,'[=23=]'-终止字节的技巧和 指针算术。这就是为什么当你这样做时

printf("%s\n", S->S);

printf 将开始一个字符一个字符地打印,直到找到 '[=23=]'-终止字节。 123 打印在屏幕上。但如你所见,那里 在 '[=23=]' 终止字节之后有更多字节。所以如果你这样做

printf("%s\n", S->S + 4);

它将打印 45678.


注释

1在C中,你从0开始计数,所以第一个元素在arr[0], 第二个 arr[1],等等