Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Poll

What programming topic would you want the next challenge to be about?  (It might be a good opportunity to focus on a subject you're not familiar with or to reinforce knowledge on one that you already know)

Control Flow
- 2 (2.2%)
Arrays, Strings, Pointers, and References
- 8 (9%)
Functions
- 4 (4.5%)
Basic object-oriented programming
- 30 (33.7%)
A bit more advanced OOP (Composition, Operator overloading, Inheritance, Virtual Functions)
- 18 (20.2%)
Templates
- 8 (9%)
Other (Explain)
- 4 (4.5%)
Working with files?  (Streams)
- 15 (16.9%)

Total Members Voted: 89


Pages: 1 ... 14 15 [16] 17 18 ... 78

Author Topic: Programming Challenges & Resources (#bay12prog) Initiative  (Read 95799 times)

ILikePie

  • Bay Watcher
  • Call me Ron
    • View Profile
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #225 on: July 09, 2010, 10:07:04 am »

I know, I didn't, what I posted there was the original code, before I tried all of the things you guys suggested. I tried doing the same thing with your brackets, and I got no error, but I couldn't pass the pointer as argument to the clearCanvas function. But that really doesn't matter anymore, I got the function working like I originally intended it to, and rewrote it work more better with what I was doing. Thanks for the help though.
Logged

DrPizza

  • Bay Watcher
    • View Profile
    • Ars Technica
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #226 on: July 09, 2010, 10:22:07 am »

I know, I didn't, what I posted there was the original code, before I tried all of the things you guys suggested. I tried doing the same thing with your brackets, and I got no error, but I couldn't pass the pointer as argument to the clearCanvas function. But that really doesn't matter anymore, I got the function working like I originally intended it to, and rewrote it work more better with what I was doing. Thanks for the help though.
You did remove them:
Code: [Select]
void clearCanvas(int width, int height, rgb *canvas[width][height]) {

Of course that does not work. That is declaring canvas as an array of array of pointer-to-rgb. What you want is a pointer to array of array of rgb. That is what I wrote. It is not what you wrote. The brackets I had were no accident. They were not optional. They were essential.

Code: [Select]
#include <stdio.h>

typedef struct _RGB
{
        unsigned char red;
        unsigned char green;
        unsigned char blue;
        unsigned char alpha;
} RGB;

void clear_canvas(int height, int width, RGB (*canvas)[height][width])
{
        RGB white = { 255, 255, 255, 255 };
        for(int i = 0; i < height; ++i)
        {
                for(int j = 0; j < width; ++j)
                {
                        (*canvas)[i][j] = white;
                }
        }
}

int main()
{
        RGB canvas[8][8];
        clear_canvas(8, 8, &canvas);
        printf("%d\n", canvas[0][0].red);
        return 0;
}


Please, stop programming by guesswork. I know C's declaration syntax is lousy: that is why I suggest using cdecl to help. You cannot just try different incantations at random until you find one that appears to work. That is not how programs should be written, and it will not yield good results.

And the code you pastebinned is very sad indeed. Global loop indices? Wow.... That's literally indefensible.

Don't cast the return value of malloc (void* is implicitly convertible to any other pointer type, and the explicit cast just masks potentially lethal errors). Do check the return value of malloc. It is obfuscatory to use pointer arithmetic for array manipulations.
« Last Edit: July 09, 2010, 10:32:56 am by DrPizza »
Logged

Normandy

  • Bay Watcher
    • View Profile
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #227 on: July 09, 2010, 10:51:58 am »

Wait seriously? I'll have to try this out for myself O.o; this comes as a surprise to me.

EDIT:
Oh, we're talking about different things. I'm talking about when you do something like this:

Code: [Select]
#include <stdio.h>

int main()
{
        int **multi_dimensional;
int *buffer;

multi_dimensional = new int*[4];
for (int i = 0; i < 4; ++i)
{
multi_dimensional[i] = new int[4];
delete buffer;
buffer = new int[i+1];
}
        printf("%zd\n", sizeof(multi_dimensional));
        printf("%p\n", multi_dimensional);
        for(int i = 0; i < 4; ++i)
        {
                printf("\t%p\n", multi_dimensional[i]);
                for(int j = 0; j < 4; ++j)
                {
                        printf("\t\t%p\n", &(multi_dimensional[i][j]));
                }
        }
}

zd
00033E88
00033EA0
00033EA0
00033EA4
00033EA8
00033EAC
00033EB8
00033EB8
00033EBC
00033EC0
00033EC4
00033ED0
00033ED0
00033ED4
00033ED8
00033EDC
00033F00
00033F00
00033F04
00033F08
00033F0C

Not contiguous in memory. If you remove the new buffer[i+1] in the middle of the memory assignment, then the array once again becomes contiguous in memory - but this is not spec. This is just ease of allocation. I'm not sure about int[][], but when creating an array using int**, you are definitely not guaranteed to get contiguous memory blocks.
« Last Edit: July 09, 2010, 11:10:59 am by Normandy »
Logged

DrPizza

  • Bay Watcher
    • View Profile
    • Ars Technica
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #228 on: July 09, 2010, 11:01:37 am »

Wait seriously? I'll have to try this out for myself O.o; this comes as a surprise to me.
Prior to C99 there was no real way to declare them dynamically, so anything created at runtime has to be an array-of-pointer. But they are true arrays of arrays, located contiguously in memory, such that the address of the entire array is equal to the address of the first element.

You can create them dynamically, too:
Code: [Select]
drpizza@lunix:~/tmp$ cat arr.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
        srand(time(NULL));
        int h = 1 + (rand() % 15);
        int w = 1 + (rand() % 15);
        int (*p)[h][w] = calloc(h * w, sizeof(int));
        printf("%d * %d\n", h, w);
        printf("%zd %zd\n", sizeof(p), sizeof(*p));
}
drpizza@lunix:~/tmp$ gcc -std=c99 -Wall arr.c
drpizza@lunix:~/tmp$ ./a.out
13 * 4
8 208
Note that this means that the result of sizeof is computed dynamically. Not even C++ can pull off that trick!
« Last Edit: July 09, 2010, 11:07:36 am by DrPizza »
Logged

Normandy

  • Bay Watcher
    • View Profile
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #229 on: July 09, 2010, 11:05:18 am »

Oh. All the books that I've ever read were telling me how pointers were arrays and vice versa, nothing but different ways of representing the same object; and it works out pretty fine in C++. I didn't know that an array of an array was different from an array of pointers.

Hrm. The more you know. That explains why you can pull a sizeof() on an array and not a pointer which has allocated an array.
« Last Edit: July 09, 2010, 11:10:14 am by Normandy »
Logged

DrPizza

  • Bay Watcher
    • View Profile
    • Ars Technica
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #230 on: July 09, 2010, 11:11:42 am »

Oh. All the books that I've ever read were telling me how pointers were arrays and vice versa, nothing but different ways of representing the same object; and it works out pretty fine in C++. I didn't know that an array of an array was different from an array of pointers.
Those books are wrong.

Arrays are not first class objects. In various contexts arrays decay to pointers, which is the source of confusion. Arrays cannot be passed to or returned from functions; they always decay to pointers when this is attempted. However, _pointers_ to arrays can be passed to and returned from functions. In C89 and C99 the array bounds must be static constants, but in C99 they can vary at runtime.
Logged

ILikePie

  • Bay Watcher
  • Call me Ron
    • View Profile
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #231 on: July 09, 2010, 11:12:49 am »

You did remove them:
Code: [Select]
void clearCanvas(int width, int height, rgb *canvas[width][height]) {
Of course that does not work. That is declaring canvas as an array of array of pointer-to-rgb. What you want is a pointer to array of array of rgb. That is what I wrote. It is not what you wrote. The brackets I had were no accident. They were not optional. They were essential.
I didn't, when I compiled I had rgb (*ptr)[8][8] = &foo. What I posted was not the code I tried to compile after working your changes into it, it was the code I started with, the code I came here with (We may be referring to two different lines though). I understand the difference between (*ptr) and *ptr to some extent, and I know those brackets are not superfluous.
And the code you pastebinned is very sad indeed. Global loop indices? Wow.... That's literally indefensible.
What's wrong with global loop indices? I figured if I was just defining the same x, i or t, variables multiple times, why shouldn't they just be global? Never mind this, qwertyuiopas cleared that up. I guess you were right, apologies sir. ;)
Don't cast the return value of malloc (void* is implicitly convertible to any other pointer type, and the explicit cast just masks potentially lethal errors). Do check the return value of malloc. It is obfuscatory to use pointer arithmetic for array manipulations.
Can you elaborate, mainly about the lethal errors part, I've read a quite a few books and tutorials that use pointer arithmetic for array manipulations and some even say that a[1] can be written as *(a + 1). This also does fit its purpose here, or I at least I think it does, I intend to write this pointer into a file eventually.

If some of these questions are dumb or obvious, then I apologize, I don't understand C as well you, or most other people do, as I have just started working with it.
« Last Edit: July 09, 2010, 04:43:10 pm by ILikePie »
Logged

qwertyuiopas

  • Bay Watcher
  • Photoshop is for elves who cannot use MSPaint.
    • View Profile
    • uristqwerty.ca, my current (barren) site.
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #232 on: July 09, 2010, 02:24:12 pm »

Using a local variable for a loop is probably easier for the compiler to optimize, posibly to the point that it doesn't even put it on the stack at all. It is also less confusing when reading the code. Also, having it global is not thread-safe in any way.

You can probably also declare white as RGB white = {255, 255, 255}; rather than setting each value after.
Logged
Eh?
Eh!

ILikePie

  • Bay Watcher
  • Call me Ron
    • View Profile
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #233 on: July 09, 2010, 04:29:37 pm »

Using a local variable for a loop is probably easier for the compiler to optimize, posibly to the point that it doesn't even put it on the stack at all. It is also less confusing when reading the code. Also, having it global is not thread-safe in any way.
Oh I see, thanks.
You can probably also declare white as RGB white = {255, 255, 255}; rather than setting each value after.
Right, forgot about this. It doesn't give any errors, but I still don't get why RGB white; white.red = 255; doesn't work. Hopefully the Doc can answer this one.
Logged

eerr

  • Bay Watcher
    • View Profile
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #234 on: July 09, 2010, 06:23:32 pm »

Using a local variable for a loop is probably easier for the compiler to optimize, posibly to the point that it doesn't even put it on the stack at all. It is also less confusing when reading the code. Also, having it global is not thread-safe in any way.
Oh I see, thanks.
You can probably also declare white as RGB white = {255, 255, 255}; rather than setting each value after.
Right, forgot about this. It doesn't give any errors, but I still don't get why RGB white; white.red = 255; doesn't work. Hopefully the Doc can answer this one.

Are you trying to perform an operation outside a function?
Logged

qwertyuiopas

  • Bay Watcher
  • Photoshop is for elves who cannot use MSPaint.
    • View Profile
    • uristqwerty.ca, my current (barren) site.
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #235 on: July 09, 2010, 10:19:19 pm »

white.red = 255 is a calculation, so not allowed in the global scope. It would work in the local scope, and initializing it in main() would work, but just not in the global scope.
Logged
Eh?
Eh!

DrPizza

  • Bay Watcher
    • View Profile
    • Ars Technica
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #236 on: July 09, 2010, 11:25:28 pm »

Using a local variable for a loop is probably easier for the compiler to optimize, posibly to the point that it doesn't even put it on the stack at all. It is also less confusing when reading the code. Also, having it global is not thread-safe in any way.
Well, you got there eventually.

Worrying about what's "easier to optimize" when we're looking at something that's so plainly going to be a source of bugs is just bizarre. Using loop variables in this way isn't just "not thread-safe". It's not re-entrant, either. Hell, not even that. You can't call any pair of methods that share the same index variable.

Most software is bug-ridden shit. Optimization should be so far down the list of priorities as to be completely ignored. Writing things that work is far more important, and already a hard enough problem before we consider issues of optimization.

Logged

ILikePie

  • Bay Watcher
  • Call me Ron
    • View Profile
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #237 on: July 10, 2010, 05:18:06 pm »

Back again, now there is something terribly wrong with my 'canvas' function, and I was hoping if someone could help me find out what is it.
So, here's the deal. I modified canvas by adding a '* 3' in the for loop like so:
Code: [Select]
RGB* canvas(int width, int height, RGB color) {
RGB *canvas; canvas = (RGB *) malloc(width * height * 3);
int t = 0;
for (t = 0; t < width * height * 3; t++) {  //right here, in bold
printf("%d ", t);
*(canvas + t) = flip_color(color);
}
return canvas;
}
before I did this everything would run perfectly, but now when I run a simple fopen command, every statement, command, or whatever succeeding the command is ignored. The code looks like this:
Code: [Select]
int main() {
int wid = 8, hei = 8;


RGB *canv;
canv = canvas(wid, hei, RGB_WHITE);  //I run canvas


printf("\nnow you see me"); //everything runs perfectly
FILE *bitmap;


bitmap = fopen("temp.bmp", "w"); //and suddenly
printf("\nnow you don't"); //nothing
This only happens if I call fopen after canvas, and doesn't happen if I remove the '* 3' mentioned above, or don't call canvas at all.

The whole thing looks like this, there's tons of crap that's work-in-progress stages, so please ignore the unfinished, messy stuff. Hopefully this is an obvious error, because it driving me mad, and believe me, I've printed out everything I know can be printed in my hunt after this elusive error.
« Last Edit: July 10, 2010, 05:21:48 pm by ILikePie »
Logged

qwertyuiopas

  • Bay Watcher
  • Photoshop is for elves who cannot use MSPaint.
    • View Profile
    • uristqwerty.ca, my current (barren) site.
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #238 on: July 10, 2010, 06:01:30 pm »

malloc() allocates in bytes, while other areas may treat it as an array. Additionally, you can set a variable in it's declaration. That first line might be better as
RGB *canvas = malloc(width * height * 3 * sizeof(RGB));

You only need the underlined change, the rest is optional, as it has the same result.

Edit:
Also, you may optionally change
*(canvas + t)
into
canvas[t]
if you feel it makes it easier to understand.
« Last Edit: July 10, 2010, 06:03:07 pm by qwertyuiopas »
Logged
Eh?
Eh!

winner

  • Bay Watcher
    • View Profile
Re: Programming Challenges & Resources (#bay12prog) Initiative
« Reply #239 on: July 10, 2010, 06:29:24 pm »

for a roguelike I made I had all the creatures in a linked list (in c++).  If I wanted all kinds of different creatures in the same linked list could I give each creature a pointer of their type that points at them, and a pointer that points at the pointer in the next creature? I am at the knowledge level of realizing that an iterator is a good idea that I should have thought of.
Logged
The great game of Warlocks!
Pages: 1 ... 14 15 [16] 17 18 ... 78