main function address

J

Joe Wright

pete said:
pete said:
CBFalconer said:
Barry Schwarz wrote:
Are you saying that calling a von-variadic function with a proper
prototype in scope will still have char, short, and float
promoted?

As usual, it depends.

The answer to the question, is "No".

[#8] No other conversions are performed implicitly;


After rethinking the "implicitly" qualifier,
I think The answer might be "it depends".
Don't go soft on us pete. You were right the first time (I think). The
implicit conversions are done according to the language rules.

The only explicit conversions are casts.
 
S

Stephen Sprunk

Leor Zolman said:
Actually, it /is/ rather unintuitive to me that in the modern world of the
flat memory model, you can't just pass a foo * in order to print its value
(and be blessed by the Standard) without first casting it to void *.
That's why I wanted to make sure. But if that's the way it is, that's the
way it is. Just one more item for my posting checklist.

The C Standard does not require a flat memory model, and C is implemented on
many systems which don't use one. While the behavior of passing an
incorrectly typed pointer works on flat memory systems, it can't be blessed
by the Standard while retaining support for non-flat systems.

S
 
E

E. Robert Tisdale

Stephen said:
The C Standard does not require a flat memory model
and C is implemented on many systems which don't use one.

Can you name one such system
which supports and ANSI/ISO C 99 compliant implementation?
While the behavior of passing an incorrectly typed pointer
works on flat memory systems,
it can't be blessed by the Standard
while retaining support for non-flat systems.

The ANSI/ISO C [89]9 standards don't specify a "flat memory model"
because they don't need to. You can assume a flat memory model
and your code will port almost everywhere.
The exceptions, if there are any, are almost never targets
for most application programs anyway.

My advice is this,
"Unless you can identify a target for your application
which does not support `a flat memory model',
it isn't worth your time to worry about it."
 
D

Dan Pop

In said:
pete said:
The answer to the question, is "No".
[#8] No other conversions are performed implicitly;

After rethinking the "implicitly" qualifier,
I think The answer might be "it depends".

You actually have to rethink the as-if rule. The compiler can perform
any conversions it wants, as long as no correct program can tell the
difference. Imagine an implementation handling the following code

void display(char c)
{
putchar(c);
}

int main()
{
char c = 'a';
display(c);
...
}

by converting char arguments to int and having the functions defined with
char parameters by expecting them to be passed as int's. If such
functions only use the LSB of their char parameters, no correct program
will be able to tell the difference. And this scenario is quite
popular on implementations passing the arguments in registers.

Dan
 
K

Keith Thompson

In said:
pete said:
CBFalconer wrote:
Barry Schwarz wrote:
Are you saying that calling a von-variadic function with a proper
prototype in scope will still have char, short, and float
promoted?

As usual, it depends.

The answer to the question, is "No".
[#8] No other conversions are performed implicitly;

After rethinking the "implicitly" qualifier,
I think The answer might be "it depends".

You actually have to rethink the as-if rule. The compiler can perform
any conversions it wants, as long as no correct program can tell the
difference.

void display(char c)
{
putchar(c);
}

int main()
{
char c = 'a';
display(c);
...
}

by converting char arguments to int and having the functions defined with
char parameters by expecting them to be passed as int's. If such
functions only use the LSB of their char parameters, no correct program
will be able to tell the difference. And this scenario is quite
popular on implementations passing the arguments in registers.

Hmm. I wouldn't actually describe that as a "conversion"; rather, I'd
say that the argument-passing convention for type char passes
int-sized chunks of data.

But both descriptions are probably equally valid.
 
D

Dan Pop

In said:
[email protected] (Dan Pop) said:
In said:
pete wrote:
CBFalconer wrote:
Barry Schwarz wrote:
Are you saying that calling a von-variadic function with a proper
prototype in scope will still have char, short, and float
promoted?

As usual, it depends.

The answer to the question, is "No".

[#8] No other conversions are performed implicitly;

After rethinking the "implicitly" qualifier,
I think The answer might be "it depends".

You actually have to rethink the as-if rule. The compiler can perform
any conversions it wants, as long as no correct program can tell the
difference.

void display(char c)
{
putchar(c);
}

int main()
{
char c = 'a';
display(c);
...
}

by converting char arguments to int and having the functions defined with
char parameters by expecting them to be passed as int's. If such
functions only use the LSB of their char parameters, no correct program
will be able to tell the difference. And this scenario is quite
popular on implementations passing the arguments in registers.

Hmm. I wouldn't actually describe that as a "conversion"; rather, I'd
say that the argument-passing convention for type char passes
int-sized chunks of data.

It's more than that: the char value is sign-extended, so the upper bytes
don't contain junk. This is useful for code optimisations: the parameter
may end up spending its entire life in a register.

Dan
 
O

Old Wolf

The easy way out for printf would be something like %q which expects a
pointer to a void function taking no arguments. However, given that %p
itself is virtually never used in real world programs, and that
%lx or %llx do work on the pointer converted to the appropriate integer
type, there is little point on adding %q.

%p is indispensable[*] on systems without flat address space
(for example, on MS-DOS it prints segment:eek:ffset, on 8051 it tells you
which page the pointer points to, and presumably on these "semi-64 bit"
contraptions that are coming out, it will print segment:eek:ffset).
Admittedly I've never used it except in recording of debug information.

Windows 3.1 crash messages printed their addresses in the same format,
so I would conjecture that Windows still uses "%p" to print the
address of where programs crashed (virtually every day, in real world PCs)

[*] Of course you can do the (unsigned char *)&ptr thing but that is tedious,
and using %lx is relying on undefined behaviour.
 
D

Dan Pop

In said:
[email protected] (Dan Pop) said:
The easy way out for printf would be something like %q which expects a
pointer to a void function taking no arguments. However, given that %p
itself is virtually never used in real world programs, and that
%lx or %llx do work on the pointer converted to the appropriate integer
type, there is little point on adding %q.

%p is indispensable[*] on systems without flat address space
(for example, on MS-DOS it prints segment:eek:ffset, on 8051 it tells you
which page the pointer points to, and presumably on these "semi-64 bit"
contraptions that are coming out, it will print segment:eek:ffset).
Admittedly I've never used it except in recording of debug information.

Windows 3.1 crash messages printed their addresses in the same format,
so I would conjecture that Windows still uses "%p" to print the
address of where programs crashed (virtually every day, in real world PCs)

Have I ever advocating dropping %p from the standard? If not, what
exactly is your point?
[*] Of course you can do the (unsigned char *)&ptr thing but that is tedious,
and using %lx is relying on undefined behaviour.

You got it wrong: using %p for function pointers *is* relying on undefined
behaviour, using %lx for function pointers converted to unsigned long is
NOT undefined behaviour (such conversions are *explicitly* allowed by the
standard).

Dan
 
O

Old Wolf

(e-mail address removed) (Dan Pop) wrote
(Old Wolf) said:
[email protected] (Dan Pop) said:
The easy way out for printf would be something like %q which expects a
pointer to a void function taking no arguments. However, given that %p
itself is virtually never used in real world programs, and that
%lx or %llx do work on the pointer converted to the appropriate integer
type, there is little point on adding %q.

%p is indispensable[*] on systems without flat address space

Have I ever advocating dropping %p from the standard? If not, what
exactly is your point?

I mistook your "%lx works" to mean "%lx works for object pointers"
when in fact you meant "%lx works for function pointers". If you had meant
what I mistook, then the conclusion "there is little point adding %q"
would not have followed, which is what I was getting at.
You got it wrong: using %p for function pointers *is* relying on undefined
behaviour, using %lx for function pointers converted to unsigned long is
NOT undefined behaviour (such conversions are *explicitly* allowed by the
standard).

Right. I was mistakenly talking about object pointers (see above)
 
D

Dave Thompson

In <[email protected]> (e-mail address removed) (Old Wolf) writes:
[*] Of course you can do the (unsigned char *)&ptr thing but that is tedious,
and using %lx is relying on undefined behaviour.

You got it wrong: using %p for function pointers *is* relying on undefined
behaviour, using %lx for function pointers converted to unsigned long is
NOT undefined behaviour (such conversions are *explicitly* allowed by the
standard).
Only in C99 <G> whose applicability I thought you still disputed </>,
and it is (still) UB "f the result cannot be represented in the
integer type" 6.3.2.3p6. For data pointers you can prevent this by
using intptr_t if present, but even then it's not guaranteed to be
*be* long, and there isn't a *printf modifier for it; the unsigned
version (as always) can be safely (no UB) cast but if that narrows the
result might not be useful; and intptr_t isn't guaranteed for
function pointers at all.

There are damn few machines nowadays where casting to either void* or
ulong shouldn't be safe, although perhaps lossy; and for those few it
should be possible to know at compile time if there's any risk it will
do anything other than yield *some* value, possibly a useless one, and
IMO failing to diagnose that would be unacceptably low QoI.

OTOH information about function addresses is usually available from
(implementation-specific) tools like the linker or equivalent, objdump
or equivalent, or the debugger, so inability to (portably) print it
from a program doesn't strike me as a serious problem.

- David.Thompson1 at worldnet.att.net
 
D

Dan Pop

In said:
In <[email protected]> (e-mail address removed) (Old Wolf) writes:
[*] Of course you can do the (unsigned char *)&ptr thing but that is tedious,
and using %lx is relying on undefined behaviour.

You got it wrong: using %p for function pointers *is* relying on undefined
behaviour, using %lx for function pointers converted to unsigned long is
NOT undefined behaviour (such conversions are *explicitly* allowed by the
standard).
Only in C99 <G> whose applicability I thought you still disputed </>,

Huh?!? The text is right there in my C89 draft:

3.3.4:

Conversions that involve pointers (other than as permitted by the
constraints of $3.3.16.1) shall be specified by means of an explicit
cast; they have implementation-defined aspects: A pointer may be
converted to an integral type. The size of integer required and the
result are implementation-defined. If the space provided is not long
enough, the behavior is undefined.

so may want to check your facts before starting to grin ;-)
and it is (still) UB "f the result cannot be represented in the
integer type" 6.3.2.3p6.


Yup, but that's far better than *unconditionally* invoking undefined
behaviour, isn't it?
For data pointers you can prevent this by
using intptr_t if present, but even then it's not guaranteed to be
*be* long, and there isn't a *printf modifier for it; the unsigned
version (as always) can be safely (no UB) cast but if that narrows the
result might not be useful; and intptr_t isn't guaranteed for
function pointers at all.


It doesn't matter: if there is a solution at all in C89, unsigned long
is good enough for the job and I know how to display it. If there is
no solution, the implementation's documentation must explicitly say so,
so we're on safe ground anyway.
There are damn few machines nowadays where casting to either void* or
^^^^^^^^^^^^^^^
ulong shouldn't be safe, although perhaps lossy; and for those few it

Since when is *unconditionally* invoking undefined behaviour safe?

To paraphrase you: there are damn few machines nowadays where void main()
isn't safe...

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,365
Latest member
BurtonMeec

Latest Threads

Top