从命令行传递参数时,* argv []中字符的大小

时间:2019-04-27 11:55:48

标签: c unicode utf-8 char

我有简单的程序。

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

int main(int argc, char *argv[])
{   
    for (int i = 0; i < strlen(argv[1]); ++i)
        printf("%x ", argv[1][i]);
    printf("\n");
}

我的运行方式

$ ./program 111
31 31 31

但是当我运行它时

$ ./program ●●●
ffffffe2 ffffff97 ffffff8f ffffffe2 ffffff97 ffffff8f ffffffe2 ffffff97 ffffff8f

此处每个都应由3个字节(UTF-8)编码:e2 97 8f,但看起来像是由3个{{1 }}。 如果unsigned始终为1个字节,我不知道ffffff的来源。

3 个答案:

答案 0 :(得分:4)

printf()是一个接受可变数量参数的函数。

任何类型小于int的整数参数都会自动转换为类型int

很显然,在您的实现中,“字符” little-round-thing3 char个组成,都具有负值。

尝试这些

printf("%x ", (unsigned char)argv[1][i]);
printf("%hhx ", argv[1][i]); // thanks to Jonathan Leffler

答案 1 :(得分:2)

  

如果sizeof(char)始终为1个字节,我不知道ffffff的来源。

根据定义,sizeof(char)为1,但是'●'不是C含义的 char ,它会生成3个 char

您的字符有明显的签名(在您的情况下, char 默认为签名的字符),每个输入●都会产生3个负代码,因为您的 char 转换为 int (在您的情况下为32b),格式%x考虑到具有这些输出的未签名参数

您将获得与printf("%x", -30);-> ffffffe2

相同的输出

注意做for (int i = 0; i < strlen(argv[1]); ++i)代价不菲,长度不变,最好保存一下或只做for (int i = 0; argv[1][i] != 0; ++i)

最好先检查 argc 至少为1,然后再查看argv[1]

答案 2 :(得分:2)

用于多代码单位代码点(除ASCII之外的所有代码)的UTF-8代码单位都在128到255之间,这意味着在ASCII范围之外。

const validateMpn = (mpn) => { const regex = /(?<style>(?<gender>\d{2})\d{4})(?<width>\d{1}[ABDE])(?<color_code>\d{3})\.(?<size_code>\d{3})/gi const match = regex.exec(mpn) if (!match) { return null } return match.groups } const str1 = '1102961D048.075' const str2 = '1200322A001.085' const match1 = validateMpn(str1) const match2 = validateMpn(str2) console.log(match1) console.log(match2)是一个vararg函数,传递给vararg部分的所有参数(除格式字符串之外的所有参数)均受标准促销的约束。

由于您的实现的裸public String getData(int row, int col, String var) { Excel.Application excelApp = new Excel.Application(); if (excelApp != null) { List<string> prop = new List<string>(var.Split(new string[] {"."}, StringSplitOptions.None)); Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(@"D:\\test.xlsx", 0, true, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0); Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelWorkbook.Sheets[prop[0]]; excelWorksheet.Select(Type.Missing); Excel.Range range = (excelWorksheet.Cells[row, col] as Excel.Range); string cellValue = range.Value.ToString(); excelWorkbook.Close(); excelApp.Quit(); return cellValue; } return null; } 是8位带符号的2s补码,表示UTF-8代码单位值为负,并且在printf()char之间,升级后,您有一个{具有该值的{1}}。

然后通过断言-1-128代表int)来撒谎printf(),{s}会导致2s补码未定义行为打印出很大的unsigned

使用%x可以得到正确的结果,尽管严格来说,应该将参数强制转换为unsigned int