24

As discussed in this question, GCC defines nonstandard unary operator && to take the address of a label.

Why does it define a new operator, instead of using the existing semantics of the & operator, and/or the semantics of functions (where foo and &foo both yield the address of the function foo())?

Community
  • 1
  • 1
Jeremy
  • 5,055
  • 1
  • 28
  • 44

2 Answers2

39

Label names do not interfere with other identifiers, because they are only used in gotos. A variable and a label can have the same name, and in standard C and C++ it's always clear from the context what is meant. So this is perfectly valid:

name:
  int name;
  name = 4; // refers to the variable
  goto name; // refers to the label

The distinction between & and && is thus needed so the compiler knows what kind of name to expect:

  &name; // refers to the variable
  &&name; // refers to the label
Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • 1
    Hi. If you can just clarify a bit regarding `Label names live in a completely separate namespace from other identifiers`..i'll be thankful. I thought `namespace` exists in `C++` :-) – Sourav Ghosh Apr 28 '15 at 08:09
  • 5
    Removed the confusing reference to "namespace". The standard uses "name space". This is not related to the C++ namespace feature. It just means the names don't interfere. – Sebastian Redl Apr 28 '15 at 08:13
9

GCC added this extension to be used in initializing a static array that will serve as a jump table:

static void *array[] = { &&foo, &&bar, &&hack };  

Where foo, bar and hack are labels. Then a label can be selected with indexing, like this:

goto *array[i];   

Standard says that

C11: 6.2.1 Scopes of identifiers (p1):

An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter.

Further it says in section 6.2.3:

If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:

label names (disambiguated by the syntax of the label declaration and use);

— the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords struct, union, or enum);

— the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the . or -> operator);

— all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants).

This means that an object and a label can be denoted by same identifier. At this point, to let the compiler know that the address of foo is the address of a label, not the address of an object foo (if exists), GCC defined && operator for address of label.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • 1
    While nicely reminiscent of my time with the Z80, I doubt this is a good idea for C at all - especially when the same result could be achieved with just slightly more work using either `switch` (GCC specifically posit this alternative) or an array of function pointers (which I just made up). Even GCC say 'don't use this unless you really need to', and it's hard to think of a situation where one _would_ really need to! Interesting to learn, but in practical terms, meh at best. – underscore_d Jan 08 '16 at 11:16
  • @underscore_d: I think the feature goes back to the days before the maintainers gcc went crazy pursuing aggressive optimizations for modern CPUs, and instead tried to give programmers tools they could use to generate efficient code for simpler CPUs in cases where performance mattered. I can easily imagine cases where the ability to perform a "goto" directly to an address in an array could allow an application to achieve a better than 10% *overall* performance gain (20% gain in part of the code where the program spends half its time). – supercat Oct 01 '16 at 22:18