12

In C one can have string literals in the form of

char *string = "string here";

integer literals:

uint8_t num = 5;

long literals:

long long bigNum = 90322L; 

floating point literals:

float decimal = 6.3f;

Is the a way to have a pointer literal? That is a literal address to a memory space. I am doing some work on an embedded project and need to hard code a value for a DMA access. I am doing something similar to the following:

uint32_t *source = 0x08000000;

While this compiles and works correctly I get the following compiler error (I'm using a variant of GCC):

cc0144: {D} warning: a value of type "int" cannot be used to initialize an entity of type "uint32_t *"
cc0152: {D} warning: conversion of nonzero integer to pointer

Is there a correct way to do this or do I just need to accept this as a fact of C? I know I can do:

uint32_t *source = (uint32_t *)0x08000000;

But that just seems very unnecessary. What is the industry way of doing this? I am also wondering if this feature exists in C++.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
secretformula
  • 6,414
  • 3
  • 33
  • 56
  • 1
    *"But that just seems very unnecessary"* May I ask why you think that's unnecessary? – dyp Jun 13 '14 at 19:45
  • 3
    In C++11 you could write a user-defined literal operator, if you so wished. – Kerrek SB Jun 13 '14 at 19:46
  • 1
    A null pointer constant is an address literal. There are no literals for non-null pointers. An integer constant with a cast like `(uint32_t *)0x08000000` is the right way to do it -- *if* that's a valid address on your system. – Keith Thompson Jun 13 '14 at 19:50
  • @dyp it seemed unnecessary because I just **assumed** there would be a built in feature to do this. I felt people need to do this frequently enough – secretformula Jun 13 '14 at 19:53
  • @secretformula You mean a built-in feature to write fixed addresses? Not a standard feature, no. The address-format is dependent on the architecture. – dyp Jun 13 '14 at 19:55
  • @secretformula: I've _never_ had to do this. The only reason I've ever heard for doing it was writing a program that altered memory in another program, or some form of DLL injection. – Mooing Duck Jun 13 '14 at 20:07
  • @MooingDuck Its a very low level program, i'm using analog devices blackfin architecture. I believe theres a way to do it using sections but it wasn't worth the time in this case to figure out how to do it. – secretformula Jun 13 '14 at 20:09
  • @secretformula Ah right, I forgot that hardware has a need of this too. That's valid. – Mooing Duck Jun 13 '14 at 20:11
  • Does the compiler complain if you treat it as a `void*` ? – Morten Jensen Jun 13 '14 at 23:22
  • @secretformula: If you're doing low-level stuff, you will eventually need to figure out how to use linker scripts. All of the serious stuff I've seen does it. And defines all their memory locations there, not hard coded in C. Or they come from a device tree, or some other kind of device description table. – Zan Lynx Jun 13 '14 at 23:47
  • @ZanLynx do you have any good references that cover this? – Shafik Yaghmour Jun 14 '14 at 06:19

3 Answers3

14

In both C and C++ the only pointer literal or constant is zero. We can go to the draft C99 standard section 6.3.2.3 Pointers:

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.55)

and:

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.56)

the correct way to deal with non-zero integer constant is to use a cast.

The equivalent section from the draft C++ standard would probably be section 5.2.10 Reinterpret cast which says:

A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined. [ Note: Except as described in 3.7.4.3, the result of such a conversion will not be a safely-derived pointer value. —end note ]

You need to see section 3.7.4.3 for all the details.

For the pointer literal reference you need section 2.14.7 Pointer literals which says:

The pointer literal is the keyword nullptr. It is a prvalue of type std::nullptr_t. [ Note: std::nullptr_t is a distinct type that is neither a pointer type nor a pointer to member type; rather, a prvalue of this type is a null pointer constant and can be converted to a null pointer value or null member pointer value. See 4.10 and 4.11. —end note ]

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
4

No, it's not. That is because literals are valid values, and the only valid pointers are addresses of objects, i.e. the result of address-of operations or of pointer arithmetic on valid pointers.

You could argue that the nullptr keyword furnishes a kind of "pointer literal"; the C++ standard calls it that. It is however the only pointer literal, and ironically it is not of pointer type.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 3
    [lex.nullptr]/1 "The pointer literal is the keyword `nullptr`." (where "pointer-literal" refers to the nonterminal *pointer-literal*) – dyp Jun 13 '14 at 19:46
  • -1: Disagree. I think the right answer was given by Shafik Yaghmour. The "literal" 0 can be used to represent a null pointer in standard C. – pablo1977 Jun 14 '14 at 01:30
  • @pablo1977: No. That's not what "literal" means at all. The literal `0` has type `int`, no ambiguity there. It is also a constant expression of value zero, and it can be *used to initialize a pointer*. But that's a very different thing from being a literal. A literal must an expression of the desired type. (For what it's worth, the accepted answer is nice, but pretty much besides the point.) – Kerrek SB Jun 14 '14 at 10:15
  • @KerrekSB: I disagree with you again. A "literal" is intended to be a language "token", so it has not any type at all. A string literal has no type `char*`. First, it is a sequence of certain characters (belonging to the source environment) enclosed in double-quotes. This token is recognized by the preprocessor, so the character string literal has not type. In a later stage is converted to an object in memory having type `char*`. However, I have to concede that you are right with the null-pointer-constant issue. It is considered a constant integer expression, which has an integer type. – pablo1977 Jun 14 '14 at 17:00
  • 1
    @pablo1977: a string literal has type "array of const char" (or suitable wide char). – Kerrek SB Jun 14 '14 at 17:03
  • @KerrekSB: In your answer you says: "literals are valid values". I think that a "literal" is just a token. You are making there the same kind of confusion as secretformulas does, I mean: merging the idea of "literal" (a token) with the concept of "constant expression", which has a type, as you well said in your comment. – pablo1977 Jun 14 '14 at 17:05
  • @KerrekSB: Of course a string literal has type `char*`, but in the very definition, a string literal is a syntactical entity. It is defined syntactically. After preprocessing stage 7 the string literal is starting to be considered an object in memory, with elements of type char. – pablo1977 Jun 14 '14 at 17:11
  • @pablo1977: Yeah, I see what you mean. Literals are first and foremost lexical tokens, but many of them do actually have types right there and then (see 2.14, e.g. integer literals have types). However, note that 5.1.1 says that "a *literal* is a primary expression", and the expression has a type, and so I hope this identification is appropriate. – Kerrek SB Jun 14 '14 at 17:11
  • @pablo1977: If a string literal had type `char *`, how would you explain [this `std::extent` resul](http://ideone.com/zxAl43)? – Kerrek SB Jun 14 '14 at 17:16
  • @KerrekSB: Oh! Interesting. I better know the C standard, where "literal" is not defined. There are only "string literals". The rest of "literals" appear just as "constants". You are citing 5.1.1 from C++11 standard, where "literal" is defined as a primary expression, having a type. That's fine. Now I want to drop my -1 vote in your answer, but it would be necessary that you make some modification to your answer, because the system has locked my vote. – pablo1977 Jun 14 '14 at 17:20
1

In C++ could you do something like the following?

uint32_t * source = reinterpret_cast<uint32_t*>(0x08000000);
Alex Riveron
  • 389
  • 1
  • 10