Does C varargs use a keyword called 'end'? - c

I have a lot of code that uses C style variable arguments. The code passes in a variable called end at the very end of our variable length function calls. And.... the code also has an enumerator called end. So far they haven't clashed (compiler error says it has an ambiguous definition: It won't tell me where the mysterious second 'end' is defined) until I changed to the VC 10.0 compiler (VS 2010).
So is end some sort of reserved keyword used especially in variable args?
I know very little about them. But I've looked at tons of documentation on variable arguments, as well as searching here, and found nothing (which could be a good thing). So I would guess the answer is that end is not a special word used with varargs. Can I get someone to confirm this?

No -- C doesn't define end as having any special meaning with varargs. When you write a function that takes a variable argument list, it's up to you to decide how to tell it how long of a list has been passed. Some popular ones are that the first argument specifies (at least indirectly) how many more arguments there are, and passing a "sentinel" value (e.g., NULL) after all the others. For a couple of examples, printf does the former, execl the latter.

Once upon a long time ago (7th Edition Unix, for example), there were three external symbols defined: etext, edata and end. These corresponded to the upper address of the code, the initialized data and the heap. It may be that your definition of end is colliding with that, somehow.

Related

Why does a function in C(or Objective C) with no listed arguments allow inputting one argument?

In C when a function is declared like void main(); trying to input an argument to it(as the first and the only argument) doesn't cause a compilation error and in order to prevent it, function can be declared like void main(void);. By the way, I think this also applies to Objective C and not to C++. With Objective C I am referring to the functions outside classes. Why is this? Thanks for reaching out. I imagine it's something like that in Fortran variables whose names start with i, j, k, l, m or n are implicitly of integer type(unless you add an implicit none).
Edit: Does Objective C allow this because of greater compatibility with C, or is it a reason similar to the reason for C having this for having this?
Note: I've kept the mistake in the question so that answers and comments wouldn't need to be changed.
Another note: As pointed out by #Steve Summit and #matt (here), Objective-C is a strict superset of C, which means that all C code is also valid Objective-C code and thus has to show this behavior regarding functions.
Because function prototypes were not a part of pre-standard C, functions could be declared only with empty parentheses:
extern double sin();
All existing code used that sort of notation. The standard would have failed had such code been made invalid, or made to mean “zero arguments”.
So, in standard C, a function declaration like that means “takes an undefined list of zero or more arguments”. The standard does specify that all functions with a variable argument list must have a prototype in scope, and the prototype will end with , ...). So, a function declared with an empty argument list is not a variadic function (whereas printf() is variadic).
Because the compiler is not told about the number and types of the arguments, it cannot complain when the function is called, regardless of the arguments in the call.
In early (pre-ANSI) C, a correct match of function arguments between a function's definition and its calls was not checked by the compiler.
I believe this was done for two reasons:
It made the compiler considerably simpler
C was always designed for separate compilation, and checking consistency across translation units (that is, across multiple source files) is a much harder problem.
So, in those early days, making sure that a function's call(s) matched its definition was the responsibility of the programmer, or of a separate program, lint.
The lax checking of function arguments also made varargs functions like printf possible.
At any rate, in the original C, when you wrote
extern int f();
, you were not saying "f is a function accepting no arguments and returning int". You were simply saying "f is a function returning int". You weren't saying anything about the arguments.
Basically, early C's type system didn't even have a way of recording the parameters expected by a function. And that was especially true when separate compilation came into play, because the linker resolved external symbols based pretty much on their names only.
C++ changed this, of course, by introducing function prototypes. In C++, when you say extern int f();, you are declaring a function that explicitly takes 0 arguments. (Also a scheme of "name mangling" was devised, which among other things let the linker do some consistency checking at link time.)
Now, this was all somewhat of a deficiency in old C, and the biggest change that ANSI C introduced was to adopt C++'s function prototype notation into C. It was slightly different, though: to maintain compatibility, in C saying extern int f(); had to be interpreted as meaning "function returning int and taking unspecified arguments". If you wanted to explicitly say that a function took no arguments, you had to (and still have to) say extern int f(void);.
There was also a new ... notation to explicitly mark a function as taking variable arguments, like printf, and the process of getting rid of "implicit int" in declarations was begun.
All in all it was a significant improvement, although there are still a few holes. In particular, there's still some responsibility placed on the programmer, namely to ensure that accurate function prototypes are always in scope, so that the compiler can check them. See also this question.
Two additional notes: You asked about Objective C, but I don't know anything about that language, so I can't address that point. And you said that for a function without a prototype, "trying to input an argument to it (as the first and the only argument) doesn't cause a compilation error", but in fact, you can pass any number or arguments to such a function, without error.

What has localness got to do with changing names of argc and argv?

This question may be silly.
C standard:(referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared)
What has the localness to the main function of the variables argc and argv got to do with changing their names? — I know that their names can be changed — I didn't understand the statement in the standard with respect to the localness of the variables. Please help me.
"Localness" means that thing that happen inside the scope of "whatever" don't affect the rest of the world. As far as the names of function parameters go, those names are not exposed to outside of the function. What is exposed (to varying degrees depending on implementation and system standards) are the function signatures (aka prototypes).
The term "localness" is not specific to main. Every function has a local scope. So does main. And its parameters of type int and (char*)[] are not visibly by name to the outside world.
What has the localness to the main function of the variables argc and
argv got to do with changing their names? — I know that their names
can be changed — I didn't understand the statement in the standard
with respect to the localness of the variables.
I think you're just overlooking the obvious. The question that the standard is trying to address there is "do I need to use the names argc and argv for the parameters of main()?" I think I've actually seen that question posed here on SO, though I wasn't able to find it in a quick search. You seem to be assuming that of course you can name the parameters whatever you want, on account of them being function parameters. The provision you ask about does nothing but affirm exactly that.
I guess you don't appreciate how someone reading the standard might take away a different impression, and you seem especially to have been thrown by the standard naming main specifically. This is all wrapped up in the facts that main is the one and only function that the standard specifies a program (as opposed to the C implementation) must supply, and that the standard designates two specific options for main's signature from which the programmer must choose. No variation from those is possible if the program is to exhibit strict conformance with the language specification. The provision you ask about just clarifies that using different parameter names does not constitute a meaningful change to the signature for this purpose.

When does macro substitution happen in C

I was reading the book "Compilers: Principles, Techniques, and Tools (2nd Edition)" by Alfred V. Aho. There is an example in this book (example 1.7) which asks to analyze the scope of x in the following macro definition in C:
#define a (x+1)
From this example,
We cannot resolve x statically, that is, in terms of the program text.
In fact, in order to interpret x, we must use the usual dynamic-scope
rule. We examine all the function calls that are currently active, and
we take the most recently called function that has a declaration of x.
It is to this declaration that the use of x refers.
I've become confused reading this - as far as I know, macro substitution happens in the preprocessing stage, before compilation starts. But if I get it right, the book says it happens when the program is getting executed. Can anyone please clarify this?
The macro itself has no notion of scope, at least not in the same sense as the C language has. Wherever the symbol a appears in the source after the #define (and before a possible #undef) it is replaced by (x + 1).
But the text talks about the scope of x, the symbol in the macro substitution. That is interpreted by the usual C rules. If there is no symbol x in the scope where a was substituted, this is a compilation error.
The macro is not self-contained. It uses a symbol external to the macro, some kind of global variable if you will, but one whose meaning will change according to the place in the source text where the macro is invoked. I think what the quoted text wants to say is that we cannot know what macro a does unless we know where it is evoked.
I've become confused reading this - as far as I know, macro substitution happens in preprocessing stage, before compilation starts.
Yes, this is how a compiler works.
But if I get it right, the book says it happens when the program is getting executed. Can anyone please clarify this?
Speaking without referring to the book, there are other forms of program analysis besides translating source code to object code (a.k.a. compilation). A C compiler replaces macros before compiling, thus losing information about what was originally a macro, because that information is not significant to the rest of the translation process. The question of the scope of x within the macro never comes up, so the compiler may ignore the issue.
Debuggers often implement tighter integration with source code, though. One could conceive of a debugger that points at subexpressions while stepping through the program (I have seen this feature in an embedded toolchain), and furthermore points inside macros which generate expressions (this I have never seen, but it's conceivable). Or, some debuggers allow you to point at any identifier and see its value. Pointing at the macro definition would then require resolving the identifiers used in the macro, as Aho et al discuss there.
It's difficult to be sure without seeing more context from the book, but I think that passage is at least unclear, and probably incorrect. It's basically correct about how macro definitions work, but not about how the name x is resolved.
#define a (x+1)
C macros are expanded early in the compilation process, in translation phase 4 of 8, as specified in N1570 5.1.1.2. Variable names aren't resolved until phase 7).
So the name x will be meaningfully visible to the compiler, not at the point where the macro is defined, but at the point in the source code where the macro a is used. Two different uses of the a macro could refer to two different declarations of variables named x.
We cannot resolve x statically, that is, in terms of the program text.
We cannot resolve it at the point of the macro definition.
In fact, in order to interpret x, we must use the usual dynamic-scope
rule. We examine all the function calls that are currently active, and
we take the most recently called function that has a declaration of x.
It is to this declaration that the use of x refers.
This is not correct for C. When the compiler sees a reference to x, it must determine what declaration it refers to (or issue a diagnostic if there is no such declaration). That determination does not depend on currently active function calls, something that can only be determined at run time. C is statically scoped, meaning that the appropriate declaration of x can be determined entirely by examining the program text.
At compile time, the compiler will examine symbol table entries for the current block, then for the enclosing block, then for the current function (x might be the name of a parameter), then for file scope.
There are languages that uses dynamic scoping, where the declaration a name refers to depends on the current run-time call stack. C is not one of them.
Here's an example of dynamic scoping in Perl (note that this is considered poor style):
#!/usr/bin/perl
use strict;
use warnings;
no strict "vars";
sub inner {
print " name=\"$name\"\n";
}
sub outer1 {
local($name) = "outer1";
print "outer1 calling inner\n";
inner();
}
sub outer2 {
local($name) = "outer2";
print "outer2 calling inner\n";
inner();
}
outer1();
outer2();
The output is:
outer1 calling inner
name="outer1"
outer2 calling inner
name="outer2"
A similar program in C would be invalid, since the declaration of name would not be statically visible in the function inner.

What's the point of function prototyping?

I'm following a guide to learn curses, and all of the C code within prototypes functions before main(), then defines them afterward. In my C++ learnings, I had heard about function prototyping but never done it, and as far as I know it doesn't make too much of a difference on how the code is compiled. Is it a programmer's personal choice more than anything else? If so, why was it included in C at all?
Function prototyping originally wasn't included in C. When you called a function, the compiler just took your word for it that it would exist and took the type of arguments you provided. If you got the argument order, number, or type wrong, too bad – your code would fail, possibly in mysterious ways, at runtime.
Later versions of C added function prototyping in order to address these problems. Your arguments are implicitly converted to the declared types under some circumstances or flagged as incompatible with the prototype, and the compiler could flag as an error the wrong order and number of types. This had the side effect of enabling varargs functions and the special argument handling they require.
Note that, in C (and unlike in C++), a function declared foo_t func() is not the same as a function declared as foo_t func(void). The latter is prototyped to have no arguments. The former declares a function without a prototype.
In C prototyping is needed so that your program knows that you have a function called x() when you have not gotten to defining it, that way y() knows that there is and exists a x(). C does top down compilation, so it needs to be defined before hand is the short answer.
x();
y();
main(){
}
y(){
x();
}
x(){
...
more code ...
maybe even y();
}
I was under the impression that it was so customers could have access to the .h file for libraries and see what functions were available to them, without having to see the implementation (which would be in another file).
Useful to see what the function returns/what parameters.
Function prototyping is a remnant from the olden days of compiler writing. It used to be considered horribly inefficient for a compiler to have to make multiple passes over a source file to compile it.
In C, in certain contexts, referring to a function in one manner is syntactically equivalent to referring to a variable: consider taking a pointer to a function versus taking a pointer to a variable. In the compiler's intermediate representation, the two are semantically distinct, but syntactically, whether an identifier is a variable, a function name, or an invalid identifier cannot be determined from the context.
Since it's not determinable from the context, without function prototypes, the compiler would need to make an extra pass over each one of your source files each time one of them compiles. This would add an extra O(n) factor for any compilation (that is, if compilation were O(m), it would now be O(m*n)), where n is the number of files in your project. In large projects, where compilation is already on the order of hours, having a two-pass compiler is highly undesirable.
Forward declaring all your functions would allow the compiler to build a table of functions as it scanned the file, and be able to determine when it encountered an identifier whether it referred to a function or a variable.
As a result of this, C (and by extension, C++) compilers can be extremely efficient in compilation.
It allows you to have a situation in which say you can have an iterator class defined in a separate .h file which includes the parent container class. Since you've included the parent header in the iterator, you can't have a method like say "getIterator()" because the return type would have to be the iterator class and therefore it would require that you include the iterator header inside the parent header creating a cyclic loop of inclusions (one includes the other which includes itself which includes the other again, etc.).
If you put the iterator class prototype inside the parent container, you can have such a method without including the iterator header. It only works because you're simply saying that such an object exists and will be defined.
There are ways of getting around it like having a precompiled header, but in my opinion it's less elegant and comes with a slew of disadvantages. Of couurse this is C++, not C. However, in practice you might have a situation in which you'd like to arrange code in this fashion, classes aside.

Calling Specific Win32 API from Delphi - Why do Exceptions Fly Without an "asm pop..."?

I'm using Delphi to make an XLL add-in for Excel, which involves making a lot of calls to the Excel4v function of xlcall32.dll. However, as I'm guessing very few Delphi experts here have worked with that specific API, I'm hoping that the problem might have been observed in other APIs too.
In C, specifically in the xlcall.h file that comes with the Microsoft Excel 2007 XLL SDK, Excel4v is defined as:
int pascal Excel4v(int xlfn, LPXLOPER operRes, int count, LPXLOPER opers[]);
In Delphi I'm using:
function Excel4v(xlfn: Integer; operRes: LPXLOPER; count: Integer;
opers: array of LPXLOPER): Integer; stdcall; external 'xlcall32.dll';
LPXLOPER is a pointer to a struct (in C) or record (in Delphi).
I've been doing my homework on declaring C functions in Delphi (this excellent article was a great help), and I think I'm declaring Excel4v properly. However, calls from Delphi code into that function cause exceptions ("access violation..." is what I keep seeing) unless they are followed by the following line:
asm pop sink; end;
Where "sink" is defined somewhere as an integer.
I have no clue about assembly... So there's no way would I have thought to try fixing the exceptions with "asm pop sink; end;". But "asm pop sink; end;" does indeed fix the exceptions. I first saw it used in this useful article on making XLLs using Delphi. Here's the most relevant quote:
"From Delphi the big stumbling block
with add-ins is the extra parameter
after the return address on the stack.
This comes free with every call to
Excel. I’ve never found out what it
holds, but so long as you throw it
away, your add-in will work fine. Add
the line asm pop variable, end; after
every call where variable can be any
global, local or object variable that
is at least 4 bytes long- integer is
fine. To repeat- THIS MUST BE INCLUDED
after every Excel4v call. Otherwise
you are constructing a time-bomb."
Basically I want to understand what's actually happening, and why. What could be causing a Win32 function to return an "extra parameter after the return address on the stack", and what does that actually mean?
Might there be another way to fix this, e.g. with a different compiler option or a different way of declaring the function?
And is there anything risky about calling "asm pop sink; end;" after every call to Excel4v...? It seems to work fine, but, as I don't understand what's going on, it feels a little dangerous...
I don't believe it's pascal vs stdcall - they are very similar calling conventions and should not result in a mismatched stack on function exit.
From the referenced article,
This would indeed be a very nice
syntax, but it is not the same as the
above array definition. Array-of
parameters are open array parameters.
They may look like any array, and they
do accept any array, but they get an
extra (hidden) parameter, which holds
the highest index in the array (the
High value). Since this is only so in
Delphi, and not in C or C++, you'd
have a real problem. (See also my
article on open arrays), since the
real number of parameters wouldn't
match.
You're getting the extra "highest array index" parameter being passed to the function. This is an int and has to be cleaned up when the function exits so that you don't wind up with a corrupted stack and crash. The article indicates how to pass arrays to C functions.
Something like:
type
PLPXLOPER = ^LPXLOPER;
And pass PLPXLOPER as the last parameter.
Your calling convention is wrong, specifically the "stdcall". The C declaration is specified as "pascal"
Stdcall passes parameters in right to left order, expects the routine to clean up, and does not use registers. Pascal, OTOH passes parameters in left to right order. Therefore, things are not happening the way the other half of the code expects in either case.
Change your Delphi declaration to also be "pascal" instead of "stdcall".
Most Windows functions use __stdcall for their calling conventions.

Resources