int pointers & characters !!

K

karthikbalaguru

Hi,

Is the following allowed in C ?

#include<stdio.h>
int main(void)
{
int *p;
char a='b';
p=&a;
*p = *p-32;
printf("%c\n",*ptr);
return 0;
}

Thx in advans,
Karthik Balaguru
 
G

Guest

Hi,

Is the following allowed in C ?

#include<stdio.h>
int main(void)
{
        int *p;
        char a='b';
        p=&a;
        *p = *p-32;
        printf("%c\n",*ptr);
        return 0;

}

get a compiler and run it. I got this

Compiling...
karth1.c
C:\bin\net\karth1.c(6) : warning C4133: '=' : incompatible types -
from 'char *' to 'int *'
C:\bin\net\karth1.c(8) : error C2065: 'ptr' : undeclared identifier
C:\bin\net\karth1.c(8) : error C2100: illegal indirection
Error executing cl.exe.
 
K

karthikbalaguru

get a compiler and run it. I got this

Compiling...
karth1.c
C:\bin\net\karth1.c(6) : warning C4133: '=' : incompatible types -
from 'char *' to 'int *'
C:\bin\net\karth1.c(8) : error C2065: 'ptr' : undeclared identifier
C:\bin\net\karth1.c(8) : error C2100: illegal indirection
Error executing cl.exe.

oh !. Yes !
It shuold printf("%c\n",*p); and not based on *ptr.

Interestingly, VC++ throws the below error and does
not allow me to complete the build / execution of the same.

error C2440: '=' : cannot convert from 'char *' to 'int *'

Thx in advans,
Karthik Balaguru
 
K

karthikbalaguru

karthikbalaguru said:




No.

But, why do i get a warning in gcc but
it is showing an error in VC++ 6.0 ?

I wonder how these compilers have
different rules at different scenarios.
Aren't the C standard made to be followed
by the compilers ? Strange !!

In VC++ 6.0 , i get the below error -
error C2440: '=' : cannot convert from 'char *' to 'int *'

Thx in advans,
Karthik Balaguru
 
G

Guest

oh !. Yes !
It shuold printf("%c\n",*p);  and not based on *ptr.

Interestingly, VC++ throws the below error and does
not allow me to complete the build / execution of the same.

error C2440: '=' : cannot convert from 'char *' to 'int *'

so why did you ask the question then?
Just typing random rubbish and then posting it to comp.lang.c
is not the way to learn a language. You have K&R. Read it.
Do the excercises. Post to comp.lang.c if you have a problem.

Pointers have type so a pointer to char is not inter-changeable
(or a ssignable to) a pointer to int. The idea is to protect
you from certain classes of error by enforcing a type system.

You *can* assign any type of pointer to void*, but this is a hole
in the type ssytem designed to make generic functions (eg. memcpy())
easier to write.
 
G

Guest

But, why do i get a warning in gcc but
it is showing an error in VC++ 6.0 ?

an implementaion is required to produce a *diagnostic*.
It is not specified if a diagnostic is a warning or an
error. I'm pretty sure you've had this explained to you before.
I wonder how these compilers have
different rules at different scenarios.
Aren't the C standard made to be followed
by the compilers ? Strange !!

they *are* following the standard

<snip>
 
J

James Kuyper

karthikbalaguru said:
But, why do i get a warning in gcc but
it is showing an error in VC++ 6.0 ?

I wonder how these compilers have
different rules at different scenarios.

They're written by different people using different methods for
different purposes.
Aren't the C standard made to be followed
by the compilers ? Strange !!

Yes, but you need to understand what it is that the C standard requires.
You seem to have some serious misconceptions about that.

The C standard requires any conforming implementation of C must
translate and correctly execute one program. It is a program chosen by
the implementor. It has to meet certain requirements set by the
standard, but those requirements allow it to be functionally equivalent
to int main(void) {return 0;}
The standard does NOT require that any other program must be translated
and correctly executed.

The C standard requires that conforming hosted implement of C must
accept any strictly conforming program (a very restricted set of
programs, that excludes virtually all useful programs). However, unlike
the "one program" described above, the standard doesn't actually require
such programs to be translated and correctly executed, only that they
must be accepted.
The standard does NOT require that any other programs be accepted.

The C standard requires that a C compiler reject a program when it
contains a #error directive that survives conditional compilation, in
which case it is required to issue a diagnostic containing the text
associated with that directive.
The standard does NOT require that any other program be rejected, no
matter how serious it's defects are, even if it contains a defect so
severe that a diagnostic is required.

The C standard requires that an implementation must issue at least one
diagnostic when processing any program that contains a syntax error, a
constraint violation, or any other situation in which the standard
specifies that a diagnostic is required. The C standard does NOT specify
that more than one diagnostic be issued, nor that the diagnostic give an
adequate explanation of the problem that made it mandatory; in fact, the
diagnostic doesn't have to explain anything: it could be the phrase
"Toodle loo!".
The standard does NOT prohibit an implementation from issuing any
diagnostics it wants, for any reason it wants. In particular, a
conforming implementation is allowed to generate misleading or even
downright false messages about your code, or your weight, or about your
ancestry.

When code has behavior that is undefined according to the C standard,
that means that the C standard imposes no constraints on it, of any
kind. A conforming implementation isn't required to accept it, nor is it
required to reject it. It isn't required to generate a diagnostic, nor
is it prohibited from generating a diagnostic. The standard doesn't
require that the code behave the way you expect it to; the standard also
doesn't prohibit it from working exactly the way you expect it to.

If you look that list over, you'll see that compilers have a lot of
freedom to decide how they will deal with defective code, while still
conforming to the C standard. Therefore, would you please stop being
surprised when different compilers conforming to the same standard
handle defective code in different ways? It's getting irritating.
 
K

karthikbalaguru

They're written by different people using different methods for
different purposes.


Yes, but you need to understand what it is that the C standard requires.
You seem to have some serious misconceptions about that.

The C standard requires any conforming implementation of C must
translate and correctly execute one program. It is a program chosen by
the implementor. It has to meet certain requirements set by the
standard, but those requirements allow it to be functionally equivalent
to int main(void) {return 0;}
The standard does NOT require that any other program must be translated
and correctly executed.

The C standard requires that conforming hosted implement of C must
accept any strictly conforming program (a very restricted set of
programs, that excludes virtually all useful programs). However, unlike
the "one program" described above, the standard doesn't actually require
such programs to be translated and correctly executed, only that they
must be accepted.
The standard does NOT require that any other programs be accepted.

The C standard requires that a C compiler reject a program when it
contains a #error directive that survives conditional compilation, in
which case it is required to issue a diagnostic containing the text
associated with that directive.
The standard does NOT require that any other program be rejected, no
matter how serious it's defects are, even if it contains a defect so
severe that a diagnostic is required.

The C standard requires that an implementation must issue at least one
diagnostic when processing any program that contains a syntax error, a
constraint violation, or any other situation in which the standard
specifies that a diagnostic is required. The C standard does NOT specify
that more than one diagnostic be issued, nor that the diagnostic give an
adequate explanation of the problem that made it mandatory; in fact, the
diagnostic doesn't have to explain anything: it could be the phrase
"Toodle loo!".
The standard does NOT prohibit an implementation from issuing any
diagnostics it wants, for any reason it wants. In particular, a
conforming implementation is allowed to generate misleading or even
downright false messages about your code, or your weight, or about your
ancestry.

When code has behavior that is undefined according to the C standard,
that means that the C standard imposes no constraints on it, of any
kind. A conforming implementation isn't required to accept it, nor is it
required to reject it. It isn't required to generate a diagnostic, nor
is it prohibited from generating a diagnostic. The standard doesn't
require that the code behave the way you expect it to; the standard also
doesn't prohibit it from working exactly the way you expect it to.

If you look that list over, you'll see that compilers have a lot of
freedom to decide how they will deal with defective code, while still
conforming to the C standard.

Ok.
Thx for that info.

Karthik Balaguru
 
G

Guest

an implementaion is required to produce a *diagnostic*.
It is not specified if a diagnostic is a warning or an
error. I'm pretty sure you've had this explained to you before.


they *are* following the standard

From X3.159-1989 (The ANSI Standard)

"A conforming implementation shall produce at least one diagnostic
meassge (identified in an implementation-defined manner) for every
translation unit that contains a violation of any syntax rule or
contraint."

So if gcc has identified warnings as well as errors as "diagnostics"
then it is compliant.
 
K

karthikbalaguru

From X3.159-1989 (The ANSI Standard)

"A conforming implementation shall produce at least one diagnostic
meassge (identified in an implementation-defined manner) for every
translation unit that contains a violation of any syntax rule or
contraint."

So if gcc has identified warnings as well as errors as "diagnostics"
then it is compliant.

Thx for that info from X3.159-1989
It was very helpful.

Karthik Balaguru
 
B

Bartc

karthikbalaguru said:
Hi,

Is the following allowed in C ?

#include<stdio.h>
int main(void)
{
int *p;

Try char *p here
char a='b';
p=&a;
*p = *p-32;

If this is to convert to upper case, there are better ways, such as
toupper() (I think requiring ctype.h, which the magic of C standard headers
means trying half-a-dozen different likely ones before resorting to the web
to find the right include...)
 
D

Darren Cubitt

karthikbalaguru said:
Hi,

Is the following allowed in C ?

#include<stdio.h>
int main(void)
{
int *p;
char a='b';
p=&a;
*p = *p-32;
printf("%c\n",*ptr);
return 0;
}

Thx in advans,
Karthik Balaguru

Why would you except to be able to assign a value of one type (char *)
to a variable of another type (int *)?

This is bad for several reasons.

Assuming a non-DS9K implementation (ie: real-world machine) with 32 bit
ints and 8 bit chars and a stack and all that, the following could
reasonably be expected to happen.

The line 'printf("%c\n", *ptr)' is going to load the 32 bits of data at
*p (which, btw, may cause an access violation), one of which will
probably be the 'b' character - but who knows what the others are?

These 32 bits will be placed on the stack in order to call printf.

printf is expecting a char (because of the '%c'). This char may be the
'b' character, or it may be one of the other random values you just
passed to it, depending on byte ordering and such.

At this point, if there is no padding in the passed values, printf will
advance it's arg pointer by one byte - but the value you passed was 4
bytes. If printf tries to read another value, it will get 24 bits of
garbage.

I'm not familiar enough with the standard to know off the top of my head
if printf is allowed to crash the machine on the way back, but I would
expect it to be able to if it has the incorrect arg size (the return
address is also (usually) stored on the stack, along with the args).

On a DS9K implementation, your code will probably launch Global
Thermonuclear War and it will be up to Matthew Broderick to save us.

The question is, why do you want to assign a char pointer to an int
pointer in the first place? I've been known to make some dubious pointer
casts in my time, but none so point(er)less as this.
 
T

TonyMc

Is the following allowed in C ?

Karthik,

all of your questions in comp.lang.c seem to come down to an attempt to
explore the /terra incognita/ that lies outside the standard. This is
like being given a map of a swamp, complete with safe pathways through
the mire, and then pestering others with questions like "Well, what
would happen if I stepped off the path onto *that* bit of (seemingly
solid) turf?"

If you are really interested in writing standard C, why don't you just
read a good text book and the ISO standard? And if you are not
interested in standard C, why don't you just try it, or perhaps read the
documentation for your particular compiler? As far as possible, try to
program in ISO standard C until you come across a situation that
requires using functions/libraries specific to your platform and
compiler, in which case use them and read their documentation. Forget
about undefined behaviour (except that there is such a thing) and learn
to use what is well defined.

Tony

P.S. Oh, and please go easy on the exclamation marks.
 
A

Antoninus Twink

karthikbalaguru said:
Is the following allowed in C ?
[snip]
The answers are all available in the C standard.

You really are a walking joke. Doesn't it get disheartening when even
your old buddies Heathfield and Thomson keep pointing at you and
laughing?
 
D

David Thompson

karthikbalaguru wrote:
Why would you except to be able to assign a value of one type (char *)
to a variable of another type (int *)?
(You meant 'expect'.)
This is bad for several reasons.

Assuming a non-DS9K implementation (ie: real-world machine) with 32 bit
ints and 8 bit chars and a stack and all that, the following could
reasonably be expected to happen.

The line 'printf("%c\n", *ptr)' is going to load the 32 bits of data at
*p (which, btw, may cause an access violation), one of which will
probably be the 'b' character - but who knows what the others are?
Correct. I would say that a (partly) garbage value is more likely, but
a (detected) access violation is possible. (Anything at all is
_permitted_ under the Dread Undefined Behavior Rule.)
These 32 bits will be placed on the stack in order to call printf.

printf is expecting a char (because of the '%c'). This char may be the
'b' character, or it may be one of the other random values you just
passed to it, depending on byte ordering and such.

At this point, if there is no padding in the passed values, printf will
advance it's arg pointer by one byte - but the value you passed was 4
bytes. If printf tries to read another value, it will get 24 bits of
garbage.
Partly correct. Variable arguments (including the data of printf) are
default-promoted, and in your example char is promoted to int. So
printf is expecting an int containing a char value. If it's invalid
(as garbage likely is) it is Undefined Behavior, but if it's in-range
OR the implementation accepts it anyway (e.g. truncates) then
advancing the varargs pointer (or equivalent) is correct and safe.
I'm not familiar enough with the standard to know off the top of my head
if printf is allowed to crash the machine on the way back, but I would
expect it to be able to if it has the incorrect arg size (the return
address is also (usually) stored on the stack, along with the args).
So _this_ specific problem doesn't apply here.

Moreover, as long as we're being semirealistic, it you do use a format
specifier that mismatches the promoted size of the argument, it is
likely to screw up values used for any subsequent arguments, but if it
makes it to the return that's likely OK. The standard does require
that printf, or any other vararg routine, that leaves some trailing
argument(s) unaccessed (after accessing leading one(s) correctly) must
return correctly. While this doesn't directly hold after a wrong-size
access, most practical implementations will cover that also.
On a DS9K implementation, your code will probably launch Global
Thermonuclear War and it will be up to Matthew Broderick to save us.
It's easy. Number of players = a null pointer constant. <G>
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top