C的流中字符的含义

时间:2019-02-02 18:19:59

标签: c language-lawyer c99 binary-data

我似乎对C语言的流抽象中的字符含义有一个盲点;我似乎无法将图片拼接在一起。
对于二进制流,字符是什么意思?

从7.19.7.1p2 ...

  

如果未设置流指向的输入流的文件结尾指示符,并且存在下一个字符,则fgetc函数将获取该字符作为转换为int的无符号字符,并前进关联的文件位置指示符流(如果已定义)。

...

假设我在字符需要16位的计算机上写了一个文件,并且我开始在字符适合7位的计算机上阅读。那么,每次调用fgetc时我实际上在阅读什么?是16位字符的一部分(即我一次读取7位)还是16位字符被“压缩”为7位表示形式而导致信息丢失?

3 个答案:

答案 0 :(得分:1)

根据规格:

  

3.7.1
1个字符
单字节字符
〈C〉适合字节的位表示形式

和:

  

3.6
1个字节
可寻址数据存储单元,其大小足以容纳执行基本字符集的任何成员   环境
注1可以表示每个地址   
注2:组成一个字节   连续的位序列,其数量为   实现定义的。最低有效位称为   低位最显著位称为高阶位。

所以你的写作机器上,char可能是一个16位的类型。在您的阅读机上,char可能是8位类型。 C要求char至少为8位类型:

  

5.2.4.2.1整数类型的大小
  ...
  —不是位字段的最小对象的位数(字节)
   CHAR_BIT 8

因此,在阅读机上,您需要进行两次fgetc调用才能读取在原始机器上写的16位字符的每一半。

答案 1 :(得分:0)

从技术上讲, int numberOfElements = Convert.ToInt32(Console.ReadLine()); int sum= 0; for (int i=0; i< numberOfElements; i++) { string input = Console.ReadLine(); sum += Array.ConvertAll(input.Split(' '), int.Parse).Sum(); } Console.WriteLine(sum); 是一种单字节类型,可以容纳-128到127之间的值;根据体系结构的不同,它也可以是char,可容纳0到255之间的值。但是,严格来说,它虽然是整数类型,但通常不用于容纳整数。您几乎总是会使用类型unsigned或其类型的一种。

实际上,类型int有两个专用用途:

它可以保存ASCII值。由于存在128个ASCII码或某些扩展版本中的255个ASCII码,因此char是实现此目的的理想类型。但是,当以这种方式使用它时,它几乎总是作为字符串的一部分出现在程序中,(在C语言中,尽管并非总是在C ++中)是一个简单的char数组。

如果您要设计一个紧凑的结构,并且想要创建一个字段(即数据成员),该字段永远不会容纳超过256个不同的值,则可能需要使用char类型也是这个目的。

请注意,对于新的C程序员而言,这里并不总是很明显。您可以将ASCII码分配给char变量,但这实际上不是C中char的属性。例如,我可以将ASCII码分配给任何整数字段。 C语言本身并不阻止这种情况。但是请记住,C字符串库函数被设计用于char的数组,而不是char的数组。

答案 2 :(得分:-2)

char*是如何声明指向char变量的指针。当您想要长度未知的字符串时,这很有用。

第一个示例:

char name[10];
strcpy (name, "type_your_name_here"); //overwrites the first argument with the second.

这里您要保留10条内存。您可能全部使用了它们,或者您的名字可能只是“ Jack”,如果我们考虑每个字符串末尾的'\0'特殊字符,则仅占用5个内存块。这意味着您还有5个未使用的作品。

也许您的名字长于10个字符,那么您将在哪里存储多余的字符?您将无法。因为您对字符数组进行了静态声明。

第二个示例:

char *name;

这意味着您刚刚声明了指针变量,您将在其中存储第一个字符的地址。它为您的使用提供了更大的自由度和灵活性。无论您的名字是长还是短,strcpystrcat之类的预定义字符串函数都可以为您处理内存分配。

简而言之:

我的理解是,在第一个示例中,您定义了字符串的起点和终点,这限制了您可以在其中容纳的内容,也浪费了内存空间。在第二个示例中,您仅指定了起点,该起点赋予了更大的使用自由度和内存经济性。我不知道第二个示例有什么弊端,这也是我第一年学习这一点。因此,专家们可能会比我更清楚地了解这个问题。