GVKun编程网logo

C – 不是uchar的比特产生int(不是c++的基本数据类型)

13

在本文中,您将会了解到关于C–不是uchar的比特产生int的新资讯,同时我们还将为您解释不是c++的基本数据类型的相关在本文中,我们将带你探索C–不是uchar的比特产生int的奥秘,分析不是c++

在本文中,您将会了解到关于C – 不是uchar的比特产生int的新资讯,同时我们还将为您解释不是c++的基本数据类型的相关在本文中,我们将带你探索C – 不是uchar的比特产生int的奥秘,分析不是c++的基本数据类型的特点,并给出一些关于c – 取消引用字符串迭代器产生int、c – 如何检查uint8_t是否作为类型而不是unsigned char存在?、char,nchar,varchar,nvarchar的区别和特点_MySQL、char数组 、char指针与字符串常量的比较的实用技巧。

本文目录一览:

C – 不是uchar的比特产生int(不是c++的基本数据类型)

C – 不是uchar的比特产生int(不是c++的基本数据类型)

当我将bit-wise应用于unsigned char时,我对C的行为感到惊讶.

取二进制值01010101b,即0x55或85.按位不应用8位表示应产生10101010b,即0xAA或170.

但是,我无法在C中重现上述内容.以下简单断言失败.

assert(static_cast<unsigned char>(0xAAu) == ~static_cast<unsigned char>(0x55u));

我用以下代码打印了0x55,0xAA和~0x55(作为uchar)的值.并且它揭示了按位并不能达到我的预期.

std::cout << "--> 0x55: " << 0x55u << ",0xAA: " << 0xAAu << ",~0x55: "
     << static_cast<unsigned>(~static_cast<unsigned char>(0x55u)) << std::endl;

--> 0x55: 85,0xAA: 170,~0x55: 4294967210

为~0x55打印的数字等于11111111111111111111111110101010b,这是32位按位而不是0x55.因此,即使我明确地将输入转换为unsigned char,〜运算符也在32位整数上运行.这是为什么?

我应用了另一个测试来查看〜运算符返回的类型.事实证明,在unsigned char输入上是int:

template <class T>
struct Print;

// inside main()    
Print<decltype(~static_cast<unsigned char>(0x55))> dummy;

产生以下编译器错误,表明结果是int类型.

error: implicit instantiation of undefined template 'Print<int>'
    Print<decltype(~static_cast<unsigned char>(0x55u))> dummy;

我究竟做错了什么?或者,如何让C从~0x55产生0xAA?

完整代码是here

解决方法

整体促销是在操作数上执行的〜我们可以通过转到 draft C++ standard部分看到这一点5.3.1一元运算符说(强调我的):

The operand of ˜ shall have integral or unscoped enumeration type; the
result is the one’s complement of its operand. Integral promotions
are performed.
The type of the result is the type of the promoted operand […]

整体促销活动将在4.5节整体促销活动中介绍,并说:

A prvalue of an integer type other than bool,char16_t,char32_t,or
wchar_t whose integer conversion rank (4.13) is less than the rank of
int can be converted to a prvalue of type int if int can represent all
the values of the source type;

为了完整性,要看到unsigned char rank小于int的等级,我们可以转到4.13整数转换等级,它表示:

The rank of a signed integer type shall be greater than the rank of
any signed integer type with a smaller size.

和:

The rank of char shall equal the rank of signed char and unsigned
char.

一种解决方案是将结果分配给unsigned char,这是安全的,因为您不必担心有符号整数溢出.

正如Ben Voigt所指出的,它将符合一个系统,其中sizeof(int)== 1和CHAR_BIT> = 32.在这种情况下,unsigned char的等级不应小于int,因此促销将是unsigned int .我们不知道实际发生的任何系统.

c – 取消引用字符串迭代器产生int

c – 取消引用字符串迭代器产生int

我收到这个错误
comparison between pointer and integer ('int' and 'const char *')

对于以下代码

#include <iostream>#include <sstream>#include <string>using namespace std;int main(){    std::string s("test string");    for(auto i = s.begin(); i != s.end(); ++i)    {        cout << ((*i) != "s") << endl;    }}

为什么解除引用字符串迭代器会产生一个int而不是std :: string?

解决方法

实际上,它不会产生一个int,它会产生一个char(因为字符串迭代器迭代字符串中的字符).由于!=的另一个操作数不是char(它是一个const char [2]),标准的促销和转换将应用于参数:

>通过整体推广将char提升为int
> const char [2]通过数组到指针的转换转换为const char *,

这是你到达编译器抱怨的int和const char *操作数的方法.

您应该将解除引用的迭代器与字符进行比较,而不是与字符串进行比较:

cout << ((*i) != 's') << endl;

“”包含一个字符串文字(类型const char [N]),”包含一个字符文字(char类型).

c – 如何检查uint8_t是否作为类型而不是unsigned char存在?

c – 如何检查uint8_t是否作为类型而不是unsigned char存在?

我有两个编译器,一个识别uint8_t(GCC ARM-EABI),另一个不识别(瑞萨M16标准工具链).

瑞萨工具链不符合ANSI C标准,因此您可以抛弃.因此uint8_t,uint16_t,…未定义为现有类型.

为了保持可移植性,我想拥有相同的类型(最好是uint8_t,因为int的含糊不清).

我的平台也是不同大小的处理器(ARM是32位,瑞萨是16位).导致int成为不同的值.

有没有办法检查uint8_t是否作为一种类型存在?

如果没有,请将它(以及其他uint16_t,uint32_t,…)声明为一种类型?

解决方法

有几种不同的方法可以解决这个问题.在需要可移植的开源项目中,常见的解决方案是使用“配置脚本”来运行以设置构建系统.然后它会像某些config.h或类似设置或未设置的HAVE_UINTX_TYPES一样[这是“配置脚本”的结果之一,并执行以下操作:

#include "config.h"
...
#ifndef HAVE_UINTX_TYPES
#include "uintx_types.h"
#endif

在一个较少“需要在几乎任何东西上运行”的系统中,你可以通过简单地将-DHAVE_UINTX_TYPES作为编译器标志的一部分来解决同样的问题.并且由于你(可能)有一些构建系统的一部分设置了不同的编译选项,为两个不同的构建选择了不同的编译器等,这应该不是一个很大的问题.

假设你很高兴你的unsigned char确实是8位,你也可以有一个uintx_types.h包含这样的东西:

typedef unsigned char  uint8_t; 
typedef unsigned short uint16_t;
typedef unsigned long  uint32_t;

另一个选择是不直接使用uint8_t和uint16_t等,但是有自己的定义[并且这些定义取决于“是ARM或Renesas”的适当构建设置,例如通过使用不同的包含选项]:

ARM / types.h中:

typedef unsigned char  u_int8;
typedef unsigned short u_int16;
typedef unsigned int   u_int32;

瑞萨/ types.h中:

typedef unsigned char  u_int8;
typedef unsigned int   u_int16;
typedef unsigned long  u_int32;

char,nchar,varchar,nvarchar的区别和特点_MySQL

char,nchar,varchar,nvarchar的区别和特点_MySQL

  对于程序中的string型字段,SQLServer中有char、varchar、nchar、nvarchar四种类型来对应(暂时不考虑text和ntext),开建立数据库中,对这四种类型往往比较模糊,这里做一下对比。

定长或变长

  所谓定长就是长度固定的,当输入的数据长度没有达到指定的长度时将自动以英文空格在其后面填充,使长度达到相应的长度;有var前缀的,表示是实际存储空间是变长的,比如varchar,nvarchar变长字符数据则不会以空格填充,比较例外的是,text存储的也是可变长。

Unicode或非Unicode

  数据库中,英文字符只需要一个字节存储就足够了,但汉字和其他众多非英文字符,则需要两个字节存储。如果英文与汉字同时存在,由于占用空间数不同,容易造成混乱,导致读取出来的字符串是乱码。Unicode字符集就是为了解决字符集这种不兼容的问题而产生的,它所有的字符都用两个字节表示,即英文字符也是用两个字节表示。而前缀n就表示Unicode字符,比如nchar,nvarchar,这两种类型使用了Unicode字符集。

基于以上两点来看看字段容量

  char,varchar 最多8000个英文,4000个汉字
  nchar,nvarchar 可存储4000个字符,无论英文还是汉字

char、varchar、nchar、nvarchar特点比较

  CHAR

  CHAR存储定长数据很方便,CHAR字段上的索引效率级高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间。

  VARCHAR

  存储变长数据,但存储效率没有CHAR高,如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么”+1″呢?这一个字节用于保存实际使用了多大的长度。

  从空间上考虑,用varchar合适;从效率上考虑,用char合适,关键是根据实际情况找到权衡点。

  TEXT

  text存储可变长度的非Unicode数据,最大长度为2^31-1(2,147,483,647)个字符。

  NCHAR、NVARCHAR、NTEXT

  这三种从名字上看比前面三种多了个”N”。和char、varchar比较起来,nchar、nvarchar最多存储4000个字符,不论是英文还是汉字;而char、varchar最多能存储8000个英文,4000个汉字。可以看出使用nchar、nvarchar数据类型时不用担心输入的字符是英文还是汉字,较为方便,但在存储英文时数量上有些损失。

使用参考(个人偏好)

  一般来说,如果含有中文字符,用nchar/nvarchar。

  如果纯英文和数字,用char/varchar。

  如果数据量非常大,又能100%确定长度且保存只是ansi字符,那么char。

  能确定长度又不一定是ansi字符或者,那么用nchar;

  对于超大数据,如文章内容,使用nText。

  其他的通用nvarchar。

char数组 、char指针与字符串常量的比较

char数组 、char指针与字符串常量的比较

数组不是基本类型,不能直接参与比较,数组与字符串及字符指针与字符串比较其实比较的是二者的地址。

例:

 
  1.  
    int isequiv(char *t)
  2.  
    {
  3.  
    if (t == "char")
  4.  
    return 1;
  5.  
    else
  6.  
    return 0;
  7.  
    }
  8.  
     
  9.  
    int main()
  10.  
    {
  11.  
    char test[] = "char";
  12.  
    char *temp = "char";
  13.  
    printf("%d", isequiv(test));//输出 0
  14.  
    printf("%d", isequiv(temp));//输出 1
  15.  
    return 0;
  16.  
    }

那么为甚么test与temp同字符串“char”比较时结果会不一样呢?其实t=="char"比较的是地址!

首先,当你这么引用一个字符串的时候 "char",它表示存储在程序的常量区的一串字符串,它返回的就是这个常量区的字符串地址比如假设这个地址是 0x004038b0 "char",那么当你使用 char *temp = "char";的时候,temp就得到了这个常量字符串的地址,也就是temp等于 0x004038b0  
或许你可以试试
 
  1.  
    char* p1 = "char";
  2.  
    char* p2 = "char";
  3.  
    char* p3 = "char";
  4.  
    char* p4 = "char";
 
这里的 p1 p2 p3 p4 的值都一样,都是指向常量区字符串 "char", 比如上面的 0x004038b0  
然而当你这么只用的时候 
char test[] = "char";  
这里情况就和上面的不一样了,这样写的时候,编译器并不是让test也指向常量区的字符串"char",而是在本地堆栈分配了一段和"char"一样大的空间,如何把常量区字符串"char" 拷贝到test
 
可以这么理解
char* p1 = "char"; p1 和 常量区的"char"是同一个东西,地址相同
char test[] = "char"; test和 常量区的"char"不是同一个东西,但是内容相同
 
  1.  
     
  2.  
    int isequiv(char *t)
  3.  
    {
  4.  
    if (t == "char")
  5.  
    return 1;
  6.  
    else
  7.  
    return 0;
  8.  
    }
以上面为例子
 
当你这么比较的时候  if (t == "char") 编译器是去比较t和"char"是不是同一个东西,它们的值(字符串的地址)是不是一样,而不是比较它们的内容是不是一样
 由前面的讲解可以知道
char* p1 = "char";    p1 和"char"的值是一样的
char test[] = "char";  test 和 "char"的值不一样,只是它们指向的字符串内容一样而已
 要比较两个字符串的内容是不是一样,用 strcmp()返回0就是一样
 比如,你那个函数可以改为
 
 
  1.  
    int isequiv(char *t)
  2.  
    {
  3.  
    if (strcmp(t, "char") == 0)
  4.  
    return 1;
  5.  
    else
  6.  
    return 0;
  7.  
    }
ps:你要理解两个感念,
 
同一个东西
内容相同的两个东西

注:字符串比较用用strcmp()函数,strcmp(test,"char")及strcmp(temp,"char")!

我们今天的关于C – 不是uchar的比特产生int不是c++的基本数据类型的分享就到这里,谢谢您的阅读,如果想了解更多关于c – 取消引用字符串迭代器产生int、c – 如何检查uint8_t是否作为类型而不是unsigned char存在?、char,nchar,varchar,nvarchar的区别和特点_MySQL、char数组 、char指针与字符串常量的比较的相关信息,可以在本站进行搜索。

本文标签: