用C ++练习思考

时间:2011-11-09 13:06:58

标签: c++

我正在学习C ++,而且我正在学习“在C ++中思考”这本书,我正在练习,我无法理解为什么在这个练习中:

  

定义int数组。获取该数组的起始地址,并使用static_cast将其转换为void*。编写一个函数,它接受void*,一个数字(表示一个字节数)和一个值(表示每个字节应该设置的值)作为参数。该函数应将指定范围内的每个字节设置为指定值。尝试使用int数组上的函数。

此解决方案有效

#include<iostream>

using namespace std;

#define PR(EX) cout << #EX << ": " << EX << endl;

void f1( void* v, size_t num_bytes, int val){

  unsigned char* p_addr = reinterpret_cast<unsigned char*>(v);
  unsigned char byte = static_cast<unsigned char>(val);

  for( size_t i = 0; i < num_bytes; i++){
    *p_addr = byte++;
    p_addr++;
  }

  PR(num_bytes);

}

int main(){

  int a[5] = { 0, 0, 0, 0, 0 };
  int value = 67;
  void* vp = static_cast<void*>(&a);    

  f1(vp, sizeof(a), value);

  unsigned char* byte = reinterpret_cast<unsigned char*>(vp);


  for( int i = 0; i < sizeof(a) / sizeof(a[0]); i++){
    cout << "a[" << i << "] = ";
    for( int j = 0; j < sizeof(int); j++){
      cout << reinterpret_cast<int*>(*byte) << " ";
      byte++;
    }
    cout << endl;
  }

  return 0;

}

虽然这个没有

#include<iostream>

using namespace std;

#define PR(EX) cout << #EX << ": " << EX << endl;

void f1( void* v, size_t num_bytes, int val){

  unsigned char* p_addr = reinterpret_cast<unsigned char*>(v);
  unsigned char byte = static_cast<unsigned char>(val);

  for( size_t i = 0; i < num_bytes; i++){
    *p_addr = byte++;
    p_addr++;
  }

  PR(num_bytes);

}

int main(){

  int a[5] = { 0, 0, 0, 0, 0 };
  int value = 67;
  void* vp = static_cast<void*>(&a);
  unsigned char* byte = reinterpret_cast<unsigned char*>(vp);

  for( size_t i = 0; i < (sizeof(a) / sizeof(a[0])); i++){
    cout << "a[" << i << "] = ";
    for( size_t j = 0; j < sizeof(int); j++){
       cout << *byte;
       byte++;
    }
    cout << endl;
  }

  PR(*byte);


  f1(vp, sizeof(a), value);    

  for( int i = 0; i < sizeof(a) / sizeof(a[0]); i++){
    cout << "a[" << i << "] = ";
    for( int j = 0; j < sizeof(int); j++){
      cout << reinterpret_cast<int*>(*byte) << " ";
      byte++;
    }
    cout << endl;
  }

  return 0;

}

差异在于我定义指针byte的位置,在函数调用之前的“工作”版本中,而在之前的“不工作”版本中。这两个版本的cout

a[0] = 
a[1] = 
a[2] = 
a[3] = 
a[4] = 
*byte: 
num_bytes: 20
a[0] = 0 0 0 0 
a[1] = 0x3b 0x8 0x40 0 
a[2] = 0 0 0 0 
a[3] = 0x4 0 0 0 
a[4] = 0 0 0 0

num_bytes: 20
a[0] = 0x43 0x44 0x45 0x46 
a[1] = 0x47 0x48 0x49 0x4a 
a[2] = 0x4b 0x4c 0x4d 0x4e 
a[3] = 0x4f 0x50 0x51 0x52 
a[4] = 0x53 0x54 0x55 0x56 

在第二个中我的字节正在以正确的方式改变,而在第一个中,在我看来,某些事情出错了。显然问题在于我定义byte指针的位置,因为我是初学者并且自己学习,所以我希望理解我的错误。

好的,我已经理解了我的错误,感谢您的建议,我修改了代码,现在它打印出我期待的内容

#include<iostream>

using namespace std;

#define PR(EX) cout << #EX << ": " << EX << endl;

void f1( void* v, size_t num_bytes, int val){

  unsigned char* p_addr = reinterpret_cast<unsigned char*>(v);
  unsigned char byte = static_cast<unsigned char>(val);

  for( size_t i = 0; i < num_bytes; i++){
    *p_addr = byte++;
    p_addr++;
  }

  PR(num_bytes);

}

int main(){

  int a[5] = { 0, 0, 0, 0, 0 };
  int value = 67;
  void* vp = static_cast<void*>(a);
  unsigned char* byte = reinterpret_cast<unsigned char*>(vp);

  for( size_t i = 0; i < (sizeof(a) / sizeof(a[0])); i++){
    cout << "a[" << i << "] = ";
    for( size_t j = 0; j < sizeof(int); j++){
      cout << reinterpret_cast<int*>(*byte);
      byte++;
    }
    cout << endl;
  }

  byte = reinterpret_cast<unsigned char*>(vp);

  f1(vp, sizeof(a), value);

  for( int i = 0; i < sizeof(a) / sizeof(a[0]); i++){
    cout << "a[" << i << "] = ";
    for( int j = 0; j < sizeof(int); j++){
      cout << *byte << " ";
      byte++;
    }
    cout << endl;
  }

  return 0;

}

a[0] = 0000
a[1] = 0000
a[2] = 0000
a[3] = 0000
a[4] = 0000
num_bytes: 20
a[0] = C D E F 
a[1] = G H I J 
a[2] = K L M N 
a[3] = O P Q R 
a[4] = S T U V 

1 个答案:

答案 0 :(得分:0)

您正在使用指针来打印数组值,并且您的打印循环会使指针前进。 在您的第二个代码清单中,您无法将指针重置为数组的开头。您的第二个循环将打印出超出数组末尾的值。

编辑:

在第一个循环中,您正在打印*byte,它被解释为8位字符值。该数组初始化为所有不是可打印ASCII值的零。如果要打印数值,请将*byte更改为static_cast<int>(*byte)

在第二个循环中,reinterpret_cast<int*>(*byte)尝试将unsigned char重新解释为指向int的指针。我不认为这就是你的意思。您应该像第一个循环一样将其更改为static_cast<int>(*byte)。或者,因为您的函数已使用有效的ASCII字符代码填充数组,所以第二个循环可以将*byte发送到cout。

我可以看到我对代码和输出的更改here