is there a way to do this...

L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Marc said:
What are you trying to do there ? Could you give me
some explanation ? Something like:
void change(int* i){
*i= 23;
char* ptr= (char*) &i;
ptr-= sizeof(int);
int* int_ptr= (int*) ptr;
*ptr+= 10;
}

OK, here's what this piece of code does.

First off, remember that C fuction arguments are passed by value. This
piece of code makes some assumptions about the structure of the memory
around the value passed into the change() function, and it's
relationship to code in the main() function.
void change(int* i){

i is a pointer to int, and on this platform, consumes a place in a
structure called a stack.

This statement sets the value of the storage pointed to by i to 23.
This is equivalent to the effects of a statement "i = 23;" in main()
char* ptr= (char*) &i;

First off, this can only legally be done in C99. Previous versions of
the C standard would call this a syntax error, as declarations cannot
follow statements, and there has already been one statement.

This defines ptr to be a pointer to characters, which points to the
location of the /argument/ on the "stack". We now know where the value
is stored for the "pass by value" argument to change()
ptr-= sizeof(int);

This decrements the pointer by the size of 1 integer. On a specific
platform, this "backs up" the pointer so that it now points to an
architectural artifact of this compiler/platform. Under certain
circumstances, the artifact that ptr now points to is the 'return
address' in main() to where a "return;" statement in change() will go
to.
int* int_ptr= (int*) ptr;

First off, this can only legally be done in C99. Previous versions of
the C standard would call this a syntax error, as declarations cannot
follow statements, and there has already been one statement.

This defines int_ptr which is a pointer to int, and points to the same
location that ptr points to. Presumably this is still the 'return
address'
*ptr+= 10;

This increments the 'return address' by 10 chars. Presumably, this
will change the 'return address' such that the termination of change()
will now skip the machine instructions in main() that implement the
"i=6;" statement

And back we go to main(), presumably to a point 10 chars past where
the compiler intended us to go. If all the factors are correct, we've
just implicitly jumped past the "i=6;" statement in main(), and the
value of i set by change() will not have been changed.

By the way, on my linux/x86/gcc, the output is 134513642, not
23...

That's because this is a non-portable, compiler-dependant,
platform-dependant, processor-dependant solution, and you don't have the
same compiler/platform/processor combination as the OP.

The OPs solution depends on
- - arguments being passed in a "stack" structure
- - a specific arrangement of hidden architectural elements on the stack
(i.e. the return address being stored immediately adjacent to the
arguments)
- - a specific size for one of the hidden architectural elements
- - a specific number of machine instruction bytes being generated
for a specific C statement
- - no compiler tricks like branch optimization, storage optimization, or
other internal arrangements that could intervene dynamically in the
code path that he is trying to skip

In other words, a completely platform-specific implementation.
Marc Boyer


- --

Lew Pitcher, IT Specialist, Enterprise Data Systems
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed here are my own, not my employer's)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)

iD8DBQFDGFxWagVFX4UWr64RAhp/AJ9T1+iG0OuKSKmMprLpy2jD5W3tGgCfe/zS
dbFwMaz6+GRo0hRQT3Vgj4s=
=njdq
-----END PGP SIGNATURE-----
 
C

Cafer =?utf-8?B?xZ5pbcWfZWs=?=

Well, Gnus users may show the referer article by pressing ^ char. Also
you are right about repling and following up.

Regards.
 
K

Keith Thompson

Agreed .... but i keep my original approach and yet want to do so....
in a way what i want is to somehow increment pc (program counter ) to
skip the execution of line i=6 .agreed this introduces architecture
dependency ,yet , implementation wise how to achive the same...

There is no way to do what you want in portable C.

There might be some ugly non-portable hack that will do what you want.
I have no idea what it might be. Even if I did, this would not be the
place to discuss it.

I can think of no reason why you'd *want* to do what you're asking.

There is nothing more to be said.
 
K

Keith Thompson

Well, Gnus users may show the referer article by pressing ^ char. Also
you are right about repling and following up.

Yes, I know about the '^' command, but it works only if the parent
article is on the server. Articles do not necessarily arrive in the
order in which they were posted, and older articles expire at
different times.

And please don't top-post. Your response belongs below, or
interspersed with, any quoted text.
 
N

Neil Ferguson

Jirka Klaue said:
Easy.

void change(int *i)
{
printf("23\n");
fclose(stdout);
}

or

void change(int *i)
{
printf("23\n");
exit(0);
}

Jirka

The first one is sweet, but is it in either case the "output of printf in
main" that appears?

Neil
 
J

Jirka Klaue

Neil Ferguson:
Jirka Klaue: .... ....
The first one is sweet, but is it in either case the "output of printf in
main" that appears?

Well, not really. But the question, if asked in an interview, is a
trick question anyway. :)

Jirka
 
J

Jeremy J Starcher

given below is a code snippet...

void main()
{
int i=5;
change(&i);
i=6;
printf("%d",i); //it should print 23 instead of 6
}



void change( int *i)
{
*i=23;
//write some code here so that output of printf in main will be 23 not
6
}

is this possible in C?

#include <stdio.h>

void change(int *i)
{
*i=23;
}


/* turn the change and printf lines into a
a wrapper function that will keep the i=6
line from running.

The i=i code is just sugar to fill in all the odd
places that semi-colons kept showing up. I ran this code
though gcc -E and watched the pre-processor output.
*/

#define change(x) i=i; change(x); while(0) {i=i
#define printf(x,y) } printf(x,y)

int main(int argc, char *argv[])
{
int i=5;
change(&i);
i = 6;
printf("%d", i);
return 0;
}

| jjs |@shraa:/tmp/c$uname -a
Linux shraa 2.6.12-gentoo-r9 #1 Wed Aug 31 02:56:45 EDT 2005 i686 AMD Athlon(tm) XP 1700+ AuthenticAMD GNU/Linux
| jjs |@shraa:/tmp/c$gcc --version
gcc (GCC) 3.3.5-20050130 (Gentoo 3.3.5.20050130-r1, ssp-3.3.5.20050130-1, pie-8.7.7.1)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

| jjs |@shraa:/tmp/c$gcc -Wall hack.c; ./a.out
23| jjs |@shraa:/tmp/c$
 
N

Novitas

Agreed .... but i keep my original approach and yet want to do so....
in a way what i want is to somehow increment pc (program counter ) to
skip the execution of line i=6 .agreed this introduces architecture
dependency ,yet , implementation wise how to achive the same...

In that case, I'd recommend something like the following:

void main()
{
int i=5;
if (change(&i))
i=6;
printf("%d",i); //it should print 23 instead of 6
}

int change( int *i)
{
*i=23;

//write some code here so that output of printf in main will be 23
not 6
return 0; /// Note, -- in the general case there would be
conditional
/// logic deciding on a 1 or 0 as the return value.
}

You could also use longjmp to cause return to a different place in the
program, but it's a lot messier and tends to excessively couple the
internals of the subroutine to the main routine.

The bottom line is that one has to live within the limits of what the
language
provides with a few prescribed exceptions (none of which are in
evidence
given the information you provided so I won't go into that)

It is necessary for the change routine to communicate in some manner
whether or not the statement that follows will or will not be executed.
Giving it a
boolean return value is the most straightforward way I can think of.
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top