簡體   English   中英

斷言值文字沒有類型是否為假?

[英]Assert that the value literals have no type is false?

我在主題,文章和SO答案中都讀到#define值沒有類型,因此我下定了決心,認為類型是容器變量的屬性,而不是值本身的屬性:

const char cVALUE = 100;    // 'cVALUE' is char with value 100, wich type is '100'?
const short sVALUE = 100;   // 'sVALUE' is short with value 100, wich type is '100'?
const int iVALUE = 100;     // 'iVALUE' is int with value 100, wich type is '100'?
#define VALUE 100           // wich type is 'VALUE'?

但是, 值后綴呢?

#define VALUE_L   100l   // 'VALUE_L' is long?
#define VALUE_UL  100ul  // 'VALUE_UL' is unsigned long?
#define VALUE_LL  100ll  // 'VALUE_LL' is long long?
#define VALUE_ULL 100ull // 'VALUE_ULL' is unsigned long long?

在上面的代碼中,類型似乎附加在值上,因此所有這些原始值都是類型化的值,與我之前閱讀的內容相反。 但是還有更多! 文本文字甚至具有限定詞,例如:

#define TEXT "Text" // '"Text"' is an array of some kind of chars.

上面#define的文本值具有類型(字符類型,如果您使用的是MSVC,我認為該字符類型可能會隨着項目設置->字符集的變化而變化,不知道是否可以在其他IDE中使用)還具有const cualifier,它是LValue而不是RValue,數字和文本文字之間的所有這些行為差異都困擾着我。

因此,假設字符類型為char ,則文字"Text"的類型為const char *const char * constconst char[5] 還是至少在上下文中推斷出正確的類型之前根本沒有類型?

並且,在C ++ 11標准中,文本文字也可以使用一些設置字符集的前綴進行類型化:

#define TEXT   L"Text"  // wide string with char type wchar_t
#define TEXTu8 u8"Text" // UTF-8 string with char type char
#define TEXTu  u"Text"  // UTF-16 string with char type char16_t
#define TEXTU  U"Text"  // UTF-32 string with char type char32_t

在考慮了所有這些內容之后,我感到非常困惑,因此我懇求一些建議:

  • 為什么常識中的文字值(和#define )沒有類型,但可以用文字指定類型? 換句話說:斷言值文字沒有類型是否為假?
  • 一個沒有后綴且沒有小數的值文字(例如100 ),可以始終視為int類型嗎?
  • 甚至考慮其前綴,文本文字的類型和限定符是什么?

在C和C ++中,預處理器和編譯器是兩個單獨的實體。

處理#define和其他預處理指令的預處理器沒有類型系統。 它操縱字符串。 這些字符代表的任何值都留給編譯器本身。

考慮

#define Y x[

即使字符串x[在C中沒有任何意義,這也是合法的預處理程序指令。但是您可以將其用作

char Y 10];

聲明和數組xchar

實際上,C預處理程序可以在源文件中用於非C語言。例如,它經常用於FORTRAN源。 由於FORTRAN沒有標准的預處理程序。

首先,您的問題:

斷言值文字沒有類型是否為假?

是。

沒有后綴且沒有小數的值文字(例如100),可以始終視為int類型嗎?

我認為默認情況下,您輸入int

即使是考慮文字前綴,Wich還是文字文字的類型和稱謂?

如果我沒記錯的話,默認類型是char []

第二,一些背景:

值文字一個類型-只是沒有明確指定它,並且並非所有類型都可以用這種方式指定。

通過聲明一個常量,您可以顯式指定類型,並為編譯器提供更多信息。

考慮到:

#define VALUE1 102

會告訴您您的值是一個int文字。

通過聲明一個const,您可以說:

static const int VALUE1 = 102;
static const float VALUE1  = 102;
static const double VALUE1 = 102;
static const unsigned int VALUE1 = 102;

進行define的正確/更好的方法(正確是define constant用於常量的相對術語)將是:

#define VALUE1 (int(102))
#define VALUE1 (float(102))
// etc ...

此時,最好添加常量。

它們是正確的,因為預處理器沒有類型。 您的例子

#define VALUE_L   100l

這並不意味着VALUE_L具有long類型。 您可以使用預處理器將該文本插入字符串文字的中間,例如this

宏沒有類型。 預處理器可以創建令牌,編譯器隨后可以將令牌解釋為具有類型,但這是切線的,因此不必執行任何此類操作。

同樣, L""文字是C ++ 03和wchar_t 文字""類型為const char[1] ,是左值。 它們是左值的原因是因為傳統上它們是用const char*指向的,並且指針必須指向左值,否則它在有用之前將變得無效,並且傳統的C數組不能為右值。

為什么常識中的文字值(和#defines)沒有類型,但是可以用文字指定類型? 換句話說:斷言值文字沒有類型是否為假?

不是。 文字均具有C ++ 11標准第2.14節中指定的類型。 在解釋文字之前,將替換預處理器宏。

沒有后綴且沒有小數的值文字(例如100),可以始終視為int類型嗎?

沒有; 十進制文字是intlong intlong long int一個可以表示該值的值。 如果需要,八進制或十六進制文字也可以不帶符號。 在2011年之前,因為它不是標准類型,所以沒有考慮long long

因此100將具有int類型,因為它足夠小,可以用int表示。

甚至考慮其前綴,文本文字的類型和限定符是什么?

沒有前綴,它是const char數組,足夠容納所有字符和零終止符。 因此, "Text"類型為char const[5]

使用前綴,字符類型將更改為您在問題中提供的類型。 數組大小仍然足夠大,可以容納包括終止符在內的所有字符。

#define是預處理器的指令,該預處理器僅執行復制和粘貼樣式替換。 預處理器不知道或不關心代碼的含義,並且沒有類型的概念。

預處理之后,編譯器處理表達式,語句,類型等。 每個表達式(除非它是重載函數的名稱或地址)都具有僅依賴於該表達式而不依賴於代碼上下文的類型。

(C ++ 11的braced-init-list沒有類型,從技術上講也不是表達式,盡管它們可以出現在許多相同的上下文中。)

因此,# #define VALUE 100對預處理器有意義,但那時類型的概念甚至不適用。 但是此后幾乎所有正確使用VALUE都將其用作表達式,並且這些表達式都具有int類型。

是的,數字后綴和字符串前綴確實會影響文字表達式的類型。 100的類型為int ,但100UL的類型為unsigned long

字面上的"Text"總是具有類型const char [5]但確切的含義,表示char可以取決於你的編譯器。 在大多數情況下,該文字將立即使用隱式的數組到指針轉換為const char*類型衰減。 (此外,為了與const發明之前的古代C代碼向后兼容,C ++允許從字符串文字中初始化char*變量,但最好不要這樣做。)

同樣,文字L"Text"具有const wchar_t [5]類型,依此類推。

#define告訴預編譯器用定義替換所有實例,因此類型在變量中不是顯式的,但可以通過查看其表示的文字值來確定。

  • 整數文字是沒有任何修飾符的int整數,否則可以將其制成long等,例如436234636L。
  • 字符串文字是普通字符串,除非在您的問題中附加修飾符。

當預處理器看到文本#define VALUE 100 ,它將存儲字符串VALUE [或類似的東西],並將“替換”存儲為100。每當預處理器以后找到VALUE ,它將替換為100 因此, VALUE沒有類型。 C語言中的文本100確實具有類型-它是一個int ,因為這就是語言規則所說的。

請記住,預處理程序替換發生在正確的編譯之前,因此預處理程序替換可以執行所有“怪異”的事情,這些事情在沒有宏的情況下很難(有時是不可能)。

同樣,預處理器只是將TEXT替換為"Text" ,此時它沒有類型。 類型僅存在於適當的編譯器中。 因此,如果您有:

#define TEXT "Text"

void myfun(int x)
{
   ... 
}

... 
myfun(TEXT);

預處理器將產生

...
myfun("Text");

只有在正確編譯代碼后,編譯器才會發現“嗯,這是一個文本字符串,它不是預期的整數”,並給您帶來一些錯誤。

至於"Text"的“類型”,它確實取決於確切的上下文。 在大多數情況下,安全的做法是將其視為const char * ,但是在某些情況下,也可以將其視為char [5]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM