Go Down

Topic: Trying to combine statements, failing miserably....... (Read 919 times) previous topic - next topic

Krupski

Hi all,

I've been playing with a small function:

Code: [Select]

char *buffer_print (char *buf, char *str, uint64_t *siz)
{
        char *ptr; /* pointer to buffer */
        uint64_t len = strlen (str); /* length of incoming string */

        *siz += len; /* update total size */

        ptr = buf = (char *) realloc (buf, *siz * sizeof (char *)); /* new buffer = old buffer + new size */

        ptr += *siz; /* move pointer to end of re-allocated buffer */
        *ptr = 0; /* null terminate last character */
        ptr -= len; /* move pointer to start of newly allocated area */

        while (len--) { /* copy incoming string to new area */
                ptr[len] = str[len];
        }
        return buf; /* return pointer to complete buffer */
}


These three lines of code are driving me nuts:

Code: [Select]

        ptr += *siz; /* move pointer to end of re-allocated buffer */
        *ptr = 0; /* null terminate last character */
        ptr -= len; /* move pointer to start of newly allocated area */


I wanted to try to combine them all into one line. I know it's hard to read, bad programming practice, etc...  don't scold me.... I don't intend to do it that way... I'm asking because I TRIED to do it for the heck of it and couldn't get it right!

I figured I would just put it all inside parentheses and it would work... I tried this:

[font=monospace]    ((ptr += *siz) = 0) -= len[/font]

doesn't work.

Ah-ha! I see my mistake!

[font=monospace]    (*(ptr += *siz) = 0) -= len;[/font]

Nope....... OH WAIT!!

[font=monospace]    &(*(ptr += *siz) = 0) -= len[/font]

Still nope..... WHAT THE HECK????????

I must be missing something simple and obvious........ but I'm not seeing it.

Any ideas?

Thanks,

-- Roger
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Graynomad

I suspect people may be more inclined to put some thought into it if there was a point to the exercise :), but I'm sure someone will accept the challenge.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Coding Badly


JimboZA

Hmmm, failing miserably meets coding badly.... that's going to work!  8)
Roy from ITCrowd: Have you tried turning it off an on again?
I'm on LinkedIn: http://www.linkedin.com/in/jimbrownza

Krupski


I suspect people may be more inclined to put some thought into it if there was a point to the exercise :), but I'm sure someone will accept the challenge.

______
Rob



What's "the point" of climbing a mountain? :)
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Krupski

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Krupski


Hmmm, failing miserably meets coding badly.... that's going to work!  8)

HA! I laughed out loud. Literally.  :)
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

JimboZA



Hmmm, failing miserably meets coding badly.... that's going to work!  8)

HA! I laughed out loud. Literally.  :)


Well I'm glad I managed to brighten someone's day so far....
Roy from ITCrowd: Have you tried turning it off an on again?
I'm on LinkedIn: http://www.linkedin.com/in/jimbrownza

joshuabardwell

I can do it in one line.

Code: [Select]
ptr += *siz; *ptr = 0; ptr -= len;

What do I win?

joshuabardwell

#9
Dec 19, 2013, 08:42 am Last Edit: Dec 19, 2013, 08:44 am by joshuabardwell Reason: 1
Ah, but in all seriousness, let's think through your problem. I think the problem you're running into is that when you try to put all the statements together, you're losing your reference back to ptr. Let's say that ptr is in memory location 10 and your string is starting at memory location 20 and has a length of 5.

Code: [Select]
*(ptr += *siz) = 0;

Should work fine. (ptr += *siz) updates memory location 10 by adding siz to it. So memory location 10 used to hold the value 20; now it holds the value 25. That operation completes and returns the value assigned, which is 25. So the parentheses evaluate to 25. Now we have:

Code: [Select]
*25 = 0;

And that works fine. *25 causes the program to look in memory location 25 and then we assign that location the value 0. Now here's the key: WHAT IS RETURNED FROM THAT OPERATION?

westfw

Quote
uint64_t len = strlen (str); /* length of incoming string */

Really?  You're just a glutton for punishment!

Code: [Select]
        ptr += *siz; /* move pointer to end of re-allocated buffer */
        *ptr = 0; /* null terminate last character */
        ptr -= len; /* move pointer to start of newly allocated area */

I don't think you can do it.  You are pretty much restricted to one assignment per statement, except for what you can accomplish with ++ and -- (neither of which will what you want.)

You can only do x += y or x = y if x is an actual variable with an address; you can't do if x is an expression (whose result is probably some temporary location.)

You DO realize that the terseness of your source code has very little to do with the efficiency of the code that the compiler will produce, right?

Hmm.  The compiler let me do pinMode(led+=4, OUTPUT);
I think I find that ... disturbing.  I really hope that you can't do (ptr-=len)[len+*siz] = 0;
(OMG, it did compile...)

AWOL

Quote
I think I find that ... disturbing.  I really hope that you can't do (ptr-=len)[len+*siz] = 0;


One of my favourite C "quirks"
Code: [Select]
int array [10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

void setup()
{
  int index = 3;
  Serial.begin (9600);
  Serial.println (index [array]);
}

void loop()
{}
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Krupski


Quote
uint64_t len = strlen (str); /* length of incoming string */

Really?  You're just a glutton for punishment!


I originally tested the "print to buffer" code in 64 bit Linux (GCC). I wanted to see how much it could take. I had a check for the malloc/realloc failing and I kept on pumping strings at it while watching my memory pool (ram and swapfile).

Finally it failed because I overran the uint32_t I was using, so I switched it to uint64_t and blasted it more.

It ran and ran until it ate up all my ram, all my swapfile and a little while longer, then finally the realloc() failed by returning a NULL.

I looked at my swap partition with a hex editor raw and found 16 gigabytes of "This is a test" filling it!

I kept on adding zeros to the test loop... I had something like "for x=0; x < 10000000000; x++" I lost track of how many zeros I had.

Anyway, that's why I had uint64_t in there... and I forgot to change it back to a more sane uint16_t for my Arduino use.  :)
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Krupski


Ah, but in all seriousness, let's think through your problem. I think the problem you're running into is that when you try to put all the statements together, you're losing your reference back to ptr. Let's say that ptr is in memory location 10 and your string is starting at memory location 20 and has a length of 5.

Code: [Select]
*(ptr += *siz) = 0;

Should work fine. (ptr += *siz) updates memory location 10 by adding siz to it. So memory location 10 used to hold the value 20; now it holds the value 25. That operation completes and returns the value assigned, which is 25. So the parentheses evaluate to 25. Now we have:

Code: [Select]
*25 = 0;

And that works fine. *25 causes the program to look in memory location 25 and then we assign that location the value 0. Now here's the key: WHAT IS RETURNED FROM THAT OPERATION?


I see what you mean... and it clearly explains why I couldn't do what I thought I should be able to do. Thanks for the clear explanation!

-- Roger
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

KeithRB

C/C++ has a defined type for buffer lengths, size_t.

Go Up