char数组的左移操作

时间:2017-11-25 22:19:43

标签: c++ arrays string char shift

我准备了一个示例程序,它将char数组的第二个元素移动到第一个位置,第三个元素移动到第二个位置等。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
int main(void) {
    char *str = (char *) malloc(10);
    strcpy(str, "123456");
    printf("%s\n", str); //123456
    str++;
    printf("%s\n", str); //23456
    str++;
    printf("%s\n", str); //3456
    str++;
    printf("%s\n", str); //456
    std::cout << str[0]; //4
}

现在我想重复这个操作但是使用移位操作,但它并没有像我期望的那样真正起作用。

#include<iostream>
int main(void){
    char tab[6] = {'1','2', '3', '4', '5', '6'};
    char *p = tab;
    for(int i = 0; i < 6; i++){
        std::cout << tab[i]; //123456
    }
    std::cout << std::endl;
    *p = *p << 8;
    std::cout << tab[0] << std::endl; //0 '\0'
    std::cout << tab[1] << std::endl; //2
    std::cout << std::endl;
    return 0;
}

如果数组名是第一个元素的指针,我希望数组名的左移操作指向数组的第二个元素,但它不会。有关如何使用移位操作重复第一个指针操作的想法吗?

5 个答案:

答案 0 :(得分:1)

  

如果数组名是第一个元素的指针,我希望左移   对数组名称的操作将指向数组的第二个元素

表达式中的数组指示符是隐式的(极少数例外)确实转换为指向其第一个元素的指针

因此在此声明中

char *p = tab;

数组指示符tab被转换为指向其第一个元素的指针,第一个元素的地址被指定给指针p

但是在这个表达式声明中

*p = *p << 8;

指针*p指向的第一个字符p的值实际上乘以功率8中等于2的值乘以256.并且字符的值被分配给指针。

因此,在此操作之后,指针具有无效值,因此程序具有未定义的行为。

您需要的是将从索引1开始的数组的所有元素复制到与索引0对应的位置。

同样在第一个程序中,您使用的是字符串,但在第二个程序中,该数组不包含字符串。

如果要移动包含字符串的字符数组的左侧元素,则代码可以看起来像在演示程序中显示的函数中实现。

#include <iostream>
#include <cstring>

char * shift_left(char *s)
{
    size_t n = std::strlen(s);

    std::memmove(s, s + 1, n);

    return s;
}


int main()
{
    char s[] = "123456";

    std::cout << s << std::endl;

    for (size_t i = 0, n = std::strlen(s); i != n; i++ )
    {
        std::cout << shift_left( s ) << std::endl;

    }

    return 0;
}

程序输出

123456
23456
3456
456
56
6

答案 1 :(得分:0)

@Provides不会移动指针,它会移动指针指向的对象中的值。 (char被隐式转换为int,右移8位,并隐式转换回char。然后该值(在具有8位char的平台上为0)将被放回{{1 }}。)

因为它指向一个char,而char(可能)是8位,我认为*做一个*p = *p << 8;是UB。

* 98.3%肯定。

答案 2 :(得分:0)

  

如果数组名是第一个元素的指针,我希望数组名的左移操作指向数组的第二个元素,但它不会。

这种期望是没有根据的。位移操作对整数类型有效,而不是指针类型。

来自https://timsong-cpp.github.io/cppwp/n3337/expr.shift#1

  

操作数应为整数或无范围的枚举类型,并执行整体促销。

     

有关如何使用移位操作重复第一个指针操作的任何想法吗?

你不应该试图这样做。我很肯定这是未定义的行为。

最好使用指针或数组元素的索引来迭代数组。

答案 3 :(得分:0)

问题在于位移和指针运算之间没有关系。

首先,让我们看看为什么第一个代码有效,第二个代码没有:

想象一下,我有一个名为'p'的指针,其值为4,指向数组的第一个位置{e,x,a,m,p,l,e}。这意味着您打印p和* p的值,您将分别得到“4”和“e”。发生这种情况是因为'e'是指针指向的值,'4'是指针指向的内存地址。如果向指针的值添加+1,则将指向此数组的第二个位置。因此,如果您再次打印p和* p的值,则分别得到“5”和“x”。

当您编写命令行*p = *p << 8时,您实际上正在将您指向的值向左移动8位。这意味着如果 p 指向第一个位置,则“e”(ASCII值等于十进制的101或十六进制的基数为0x65)将被移位8位并变为0x0,是一个空字符。但是,指针的值将保持不变。如果打印p和* p值,则分别得到“4”和 null 值。

另一方面,如果您编写p = p << 8,您将更改指针值(以及它指向的内容)。如果p的值为“4”,它将成为a 转移后“1024”。

使用指针算法比使用位移更容易实现所需的功能。

答案 4 :(得分:0)

关于:

*p = *p << 8;

这是取数组的第一个字节(最初包含0x31)

并将字节移位8位(因此它现在包含0x00)

然后将结果存储回数组的第一个字节。

这不会改变整个阵列。