在C - 内存方向中反转字符串

时间:2015-08-24 15:26:59

标签: c pointers

最近我一直在学习C语言中的字符串和指针,并且已经了解到你可以使用指针算法在C中做一些非常酷的事情,反转字符串就是其中之一。以下是我正在使用的代码:

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

void print_reverse_string(char s[])
{
    size_t length = strlen(s);

    char *beginning = s;
    char *end = beginning + length - 1;    

    while(end >= beginning)
    {
        printf("%c", *end);
        end = end - 1;
    }    
}

int main() 
{
    printf("Please enter string to reverse: ");
    char input_string[20];
    fgets(input_string, 20, stdin);

    /* Get rid of new line character from fgets function */
    input_string[strlen(input_string) - 1] = '\0';

    printf("Reversed string: ");
    print_reverse_string(input_string);

    return 0;
}

我的关注点从以下代码行开始:

char *end = beginning + length - 1;

这假定数组的结束内存位置始终大于起始内存位置。这是我作为C程序员应该关注的事情,还是我可以保证

&randomArray[0] < &randomArray[1] < &randomArray[2] < .... < &randomArray[lastElement]

只是我一直在阅读有关不同内存空间以及某些空间如何向上生长而其他空间向下生长的情况,例如,堆栈向下生长并且堆积向上增长,并认为可能存在这种可能性阵列向下扩展。

这可能发生在某个架构上,还是我过度思考这种可能性?

3 个答案:

答案 0 :(得分:4)

char *end = beginning + length - 1;时,

length == 0会导致未定义的行为。示例:“结束数组的内存位置将始终更大”可能是真的,期望代码希望它是假的。诸如beginning + length - 1之类的指针算法仅在从对象的开头到结束之后的1个对象有效。所以beginning + 0 - 1是UB。

后续(如在数组中)对象的地址按递增顺序进行比较 - 无论其基础值如何,但算法仅在较窄范围内有效。

最好做

char *end = beginning + length;
while(end > beginning) {  
  end = end - 1; 
  printf("%c", *end);
}

附带问题:如果通过fgets()读取的第一个字符是'\0',则以下代码会尝试input_string[SIZE_MAX] = '\0'

 // do not use
input_string[strlen(input_string) - 1] = '\0';
// alternatives
if (*input_string) input_string[strlen(input_string) - 1] = '\0';
// or
input_string[strcspn(input_string, "\n")] = '\0';

答案 1 :(得分:3)

C数组总是在内存中连续分配,从最低地址到最高地址。

答案 2 :(得分:1)

  

这假定数组的结束内存位置始终大于起始内存位置。

是的,你的假设是正确的。数组将其元素存储在连续的内存位置并按递增顺序存储。