what different between 1 and 2, why?

C

chunpulee

int main()
{
char **buf;
int nodesize = 1024;
int nodenum = 10;
int i;

buf = (char **)malloc(nodenum);
for (i=0; i<nodenum; i++) {
buf = (char *)malloc(nodesize);
memset(buf, 0, nodesize);
sprintf(buf, "%d", (i+1)*1000+10);
if (i == 0) {
printf("%p: %s\n", buf[0], buf[0]); /* 1 */
}
}
printf("%p: %s\n", buf[0], buf[0]); /* 2 */

return 0;
}
 
B

Ben Bacarisse

It is best to put the question in the body of your message:

| what is different between 1 and 2, why?
int main()
{
char **buf;
int nodesize = 1024;
int nodenum = 10;
int i;

buf = (char **)malloc(nodenum);

The bit that is bothering you is here. 10 is probably not big enough
for 10 char *s. Try:

buf = malloc(nodenum * sizeof *buf);
for (i=0; i<nodenum; i++) {
buf = (char *)malloc(nodesize);
memset(buf, 0, nodesize);
sprintf(buf, "%d", (i+1)*1000+10);
if (i == 0) {
printf("%p: %s\n", buf[0], buf[0]); /* 1 */
}
}
printf("%p: %s\n", buf[0], buf[0]); /* 2 */

return 0;
}


(1) You are missing #includes.
(2) You don't need the casts.
(3) Why memset the buffer if you set is to string on the next line.
(4) You should check the return from malloc.
(5) %p expects a void * and this is one of the rare places you *do* need
a cast: printf("%p: %s\n", (void *)buf[0], buf[0]);

Do you have text you are learning from?
 
K

Keith Thompson

Please include the question in the body of the article, not just in
the subject:

what different between 1 and 2, why?

Add:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

If your compiler didn't warn you about the implicit or missing
declaratins for malloc, memset, sprintf, and printf, crank up the
warning level until it does.
int main()

Slightly better:
int main(void)
{
char **buf;
int nodesize = 1024;
int nodenum = 10;
int i;

buf = (char **)malloc(nodenum);

Here you allocate just 10 bytes, but you treat buf as a pointer to the
first element of an array of 10 char* objects. Unless your system has
1-byte pointers, this isn't going to work.

Don't bother to cast the result of malloc; it's not necessary,
and it can mask certain errors (like forgetting the required
"#include <stdlib.h>").

I changed to the above line to:
buf = malloc(nodenum * sizeof *buf);
and the program worked.
for (i=0; i<nodenum; i++) {
buf = (char *)malloc(nodesize);


Again, drop the unnecessary cast.
memset(buf, 0, nodesize);
sprintf(buf, "%d", (i+1)*1000+10);
if (i == 0) {
printf("%p: %s\n", buf[0], buf[0]); /* 1 */
}
}
printf("%p: %s\n", buf[0], buf[0]); /* 2 */

return 0;
}


You're using "%p" to print char* values. "%p" expects a void*
argument. As it happens, the standard guarantees that void* and char*
have the same representation, so this should work. But it's a good
idea to get into the habit of casting pointer arguments to void* when
using "%p" (unless they're already of type void*). (Most casts are
unnecessary; arguments to printf, where the compiler doesn't have
enough information to perform the right implicit conversion, are an
exception.)
 
O

Old Wolf

 (2) The correct allocation size calculation.

/* 1 */ ---> does the printf() once, on the first iteration of the loop.
/* 2 */ ---> does the printf() once, after the final iteration of the loop.

There's no significant difference in your program.

I think he was asking why he gets different outputs
on his system from the two printfs, when they ought
to be printing the same thing.

(I'll leave you to answer that question, since the
details of it are off topic ;)
 
A

Andy

int main()
{
    char **buf;
    int nodesize = 1024;
    int nodenum = 10;
    int i;

    buf = (char **)malloc(nodenum);

Should be:
buf = malloc(nodenum * sizeof *buf);

BTW, (char *) on most machine is 4 bytes, not one byte...

Here you are allocating only 10 bytes, but later you are using {buf +
i* sizeof (char *)} when accessing buf...

    for (i=0; i<nodenum; i++) {
        buf = (char *)malloc(nodesize);
        memset(buf, 0, nodesize);


It is really not necessary, because sprintf() will put a '\0' at the
end of the string.....

        sprintf(buf, "%d", (i+1)*1000+10);
        if (i == 0) {
            printf("%p: %s\n", buf[0], buf[0]);  /* 1 */
        }
    }
    printf("%p: %s\n", buf[0], buf[0]);  /* 2 */


So, 1 and 2 will print out different value....
 
B

Boon

Andy said:
BTW, (char *) on most machine is 4 bytes, not one byte...

You seem to be confusing bytes and octets.

An octet is eight bits, while a byte is any number of bits.

In the context of C, there cannot be less than 8 bits in a byte.
However, there are platforms with 16-bit bytes and 32-bit bytes.

I would also question your assertion that char pointers are 4-bytes wide
on most machines, even assuming you meant 32-bits wide. In the embedded
world, there are /many/ platforms where pointers are 16-bits wide, and
even the mainstream desktop world (i.e. not Alpha, MIPS, SPARC) has had
64-bit processors since 2003.

Regards.
 
J

James Kuyper

Boon said:
You seem to be confusing bytes and octets.

I don't think so; on most commonly-used machines, bytes and octets are
the same, so you can't derive any conclusion about whether or not he's
confusing them from a statement like the one above. The issue that's
relevant in this context is the number of bytes, not the number of octets.

I think he is overestimating the ubiquity of 4 byte pointers. More
important, his statement would have been more useful if, like other
people's responses, it it had not mentioned a specific size. The
important fact is that sizeof(char*) is not necessarily 1; that any
particular value greater than 1 is commonplace isn't really relevant.
 

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,262
Messages
2,571,049
Members
48,769
Latest member
Clifft

Latest Threads

Top