Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Xanthir
My HERO!!!
Posts: 5400
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: Coding: Fleeting Thoughts

Postby Xanthir » Fri Jul 13, 2012 11:28 pm UTC

Shameless promotion! I've been writing the Syntax spec for CSS, largely just to replace the grammar-based approach that 2.1 uses with a state-machine-based one, and I finally translated the spec text into JS (so I could test it). If anyone's interested in bug-testing it, or lightly rewriting it to use modern modularizing practices, it's up on Github.

Fuller explanation on my blog.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

User avatar
Steax
SecondTalon's Goon Squad
Posts: 3038
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: Coding: Fleeting Thoughts

Postby Steax » Sat Jul 14, 2012 2:01 am UTC

How... what. I was just looking for a good JS CSS parser for a project (in Node JS). I'm not yet in the stage where I need it, but I'm watching the repo.

Also, is there anything different in particular with the syntax? That's a lot to go through.
In Minecraft, I use the username Rirez.

User avatar
Xanthir
My HERO!!!
Posts: 5400
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: Coding: Fleeting Thoughts

Postby Xanthir » Sat Jul 14, 2012 2:34 am UTC

Steax wrote:How... what. I was just looking for a good JS CSS parser for a project (in Node JS). I'm not yet in the stage where I need it, but I'm watching the repo.

Heh, cool.

Also, is there anything different in particular with the syntax? That's a lot to go through.

Only a few small bits. Obviously I can't change CSS's syntax overall - the point of the new Syntax spec is to document the missing parts of error-handling, and to make the existing error-handling match reality better where the current grammar doesn't. If you're writing valid CSS in the first place, no worries, this should parse everything identically to how browsers do, unless I'm buggy someplace.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Sat Jul 14, 2012 4:23 am UTC

Xeio wrote:You wouldn't use -4 off of the allocated address, you allocate memory, then use +4 (or whatever) as the address of your actual array. You just have to make sure to allocate the extra bytes when you allocate the array (and of course make sure to pass the original allocated memory address when you free and such).

Thesh wrote:Let's say you allocate this 8 bytes of memory and assign is to a variable a. You can then set a second pointer b to the element at index 1. b[0] = a[1] and b[-1] = a[0].

Okay, so you allocate memory, either with malloc or just an array declaration, and then grab the address of the second element and you can index it as an array. That makes sense. But that will actually be a pointer rather than an array. And from what I recall, you can't just cast a pointer to an array (or at least I couldn't get it to work, back when I learned a little C, and when I googled it, it seemed like you couldn't do it, at least not in a straightforward way).

I know pointers and arrays are mostly interchangeable, but also that they're not in certain cases, so I thought they'd be clearly distinguished. Is it usual to use "array" to mean either an actual array type or a pointer "pseudoarray"? Or am I missing something and you somehow end up with a true array?
(It occurs to me now that maybe when C programmers make dynamically-sized arrays, they're actually using pointers?)


FT: on another note, this is - almost precisely* - the keyboard of my dreams. Now I just have to wait until "somewhen" to get one :-(
* it's lacking a scroll wheel. The final keyboard will have a third mouse button (probably as a "thin horizontal strip of plastic between the buttons that are already there"), but there's no mention of a scrollwheel. It would be cool if the "thin plastic strip" had sensors so you could lightly swipe it to scroll...

User avatar
PM 2Ring
Posts: 3700
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Coding: Fleeting Thoughts

Postby PM 2Ring » Sat Jul 14, 2012 6:42 am UTC

troyp wrote:Okay, so you allocate memory, either with malloc or just an array declaration, and then grab the address of the second element and you can index it as an array.

Exactly.

troyp wrote:But that will actually be a pointer rather than an array. And from what I recall, you can't just cast a pointer to an array (or at least I couldn't get it to work, back when I learned a little C, and when I googled it, it seemed like you couldn't do it, at least not in a straightforward way).

I know pointers and arrays are mostly interchangeable, but also that they're not in certain cases, so I thought they'd be clearly distinguished. Is it usual to use "array" to mean either an actual array type or a pointer "pseudoarray"? Or am I missing something and you somehow end up with a true array?
(It occurs to me now that maybe when C programmers make dynamically-sized arrays, they're actually using pointers?)


A C array variable is essentially a constant pointer to the zeroth element of the array. So a pointer to an array element behaves (mostly) just like an array. Note that, if desired, you can declare a pointer to a whole array of fixed size; when you increment such a pointer it points to the next array rather than the next array element. This can be handy when manipulating multidimensional arrays.

Here's a short extract from K&R (2nd edition) on the topic of arrays and pointers. In this extract, a is an array, pa is a pointer to data of the same type as the array elements, eg

int a[10], *pa;

K&R2, p.99
The correspondence between indexing and pointer arithmetic is very close. By definition, the value of a variable or expression of type array is the address of element zero of the array. Thus after the assignment

pa = &a[0];

pa and a have identical values. Since the name of an array is a synonym for the location of the initial element, the assignment pa=&a[0] can also be written as

pa = a;

Rather more surprising, at least at first sight, is the fact that a reference to a[i] can also be written as *(a + i). In evaluating a[i], C converts it to *(a + i) immediately; the two forms are equivalent. Applying the operator & to both parts of this equivalence, it follows that &a[i] and a+i are identical: a+i is the address of the i-th element beyond a.

[...]

There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Sat Jul 14, 2012 7:14 am UTC

troyp wrote:
Xeio wrote:You wouldn't use -4 off of the allocated address, you allocate memory, then use +4 (or whatever) as the address of your actual array. You just have to make sure to allocate the extra bytes when you allocate the array (and of course make sure to pass the original allocated memory address when you free and such).

Thesh wrote:Let's say you allocate this 8 bytes of memory and assign is to a variable a. You can then set a second pointer b to the element at index 1. b[0] = a[1] and b[-1] = a[0].

Okay, so you allocate memory, either with malloc or just an array declaration, and then grab the address of the second element and you can index it as an array. That makes sense. But that will actually be a pointer rather than an array. And from what I recall, you can't just cast a pointer to an array (or at least I couldn't get it to work, back when I learned a little C, and when I googled it, it seemed like you couldn't do it, at least not in a straightforward way).

I know pointers and arrays are mostly interchangeable, but also that they're not in certain cases, so I thought they'd be clearly distinguished. Is it usual to use "array" to mean either an actual array type or a pointer "pseudoarray"? Or am I missing something and you somehow end up with a true array?
(It occurs to me now that maybe when C programmers make dynamically-sized arrays, they're actually using pointers?)

Arrays aren't pointers or vice versa, and you shouldn't be thinking of them as such. An array is a sequence of elements and a pointer is a value that points to some position in memory.

Conceptually they don't really have anything to do with each other, except for the fact that you access an array by using a pointer. If there's a row of houses somewhere you use the street address to find the particular house you're looking for. You don't ask, "I've got a street address - now how do I convert that into a row of houses?"

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Sat Jul 14, 2012 7:32 am UTC

PM 2Ring wrote:
There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.

And another, absolutely critical one: sizeof (along with typeid and decltype in C++, and typeof in GNU's extension) will return different things for arrays and pointers.

This one is actually way more important to remember than what K&R say, since the compiler will yell at you for that, while carelessness with sizeof etc. will silently do the wrong thing. It's why I tend to jump on people who say that arrays and pointers are equivalent in C/C++.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Sun Jul 15, 2012 5:36 am UTC

PM 2Ring wrote:A C array variable is essentially a constant pointer to the zeroth element of the array. So a pointer to an array element behaves (mostly) just like an array. Note that, if desired, you can declare a pointer to a whole array of fixed size; when you increment such a pointer it points to the next array rather than the next array element. This can be handy when manipulating multidimensional arrays.

Here's a short extract from K&R (2nd edition) on the topic of arrays and pointers. In this extract, a is an array, pa is a pointer to data of the same type as the array elements, eg

int a[10], *pa;

Huh, you're right. That is the main difference: arrays are constant. I remember reading all this (I read K&R up to arrays & pointers), but I didn't take in all the details. I knew there were differences, but apart from sizeof behaviour, I was blurry on what they were. I knew there was something different about declaration and/or assignment of arrays, but I couldn't remember what. I just had a vague memory of arrays being "finicky" :-) That's what it is, though, they're constant. I didn't realize it was that simple.

Also, I can't read that passage without getting evil ideas (like assigning a 1 to a variable second_elts and indexing it with arrays to access the second members of the arrays - and oddly you don't even have to cast the int before you can index it)

Sc4Freak wrote:Arrays aren't pointers or vice versa, and you shouldn't be thinking of them as such. An array is a sequence of elements and a pointer is a value that points to some position in memory.

Conceptually they don't really have anything to do with each other, except for the fact that you access an array by using a pointer. If there's a row of houses somewhere you use the street address to find the particular house you're looking for. You don't ask, "I've got a street address - now how do I convert that into a row of houses?"

I think you're exaggerating, at least - and that's a pretty big "except" you just glossed over. Pointers may be conceptually distinct from arrays in typical usage, but they *can* be used as arrays. Moreover arrays are implemented like pointers. If "row of houses" actually meant "the address of the first house in the row", then suddenly converting a street address into a row of houses makes a lot more sense (there's just a question of the number of houses, which isn't explicit in either definition or conversion).

Maybe you're saying you *shouldn't* think in those terms, although you can. But it's clear to me that C programmers do sometimes do this (not sure about C++ programmers). People were just discussing arrays starting at a negative index, where the arrays were actually pointers that were being indexed. And last night I looked up variable-length arrays in C, wondering if they were implemented using pointers as well, and it seems they often are (not always, some people defined arrays and then changed the amount of memory they controlled using a "realloc" function). And C programmers are not only *using* pointers like they were arrays, they're *calling* them arrays, at least in certain contexts - which is the thing that initially confused me, because I'd expected them to distinguish between them, even when they were used in the same way.

As far as casting an pointer to an array goes, I tried that when I was first learning about arrays (and I was in the middle of wrestling with the compiler about some program). Looking at it now, I can see why the conversion would be problematic. For one thing, an array declaration tells the compiler how many elements the array has, while an pointer-to-array-cast would leave that information missing. You'd have to either provide the information with the cast somehow or make a default assumption (eg. arrays resulting from conversion always have 1 element). Maybe there are other problems, and it wouldn't make sense to allow the cast, or maybe there's actually no scenario where it's really necessary. I don't have a deep understanding a C (read: "I don't even know half the basics"), so it's hard for me to judge. But it's not a *conceptual error* to discuss it.

EvanED wrote:And another, absolutely critical one: sizeof (along with typeid and decltype in C++, and typeof in GNU's extension) will return different things for arrays and pointers.

This one is actually way more important to remember than what K&R say, since the compiler will yell at you for that, while carelessness with sizeof etc. will silently do the wrong thing.

Yeah, I know about sizeof. I didn't even learn it when I learned C, I just read about somewhere and it stuck in my mind because it seemed like such a gotcha (and also because it struck me as a really awful design decision). It's certainly more dangerous than the "constness" of arrays, but it strikes me as a very arbitrary sort of distinction. I mean, there's nothing about how arrays work that dictate this difference in sizeof behaviour, it's just imposed purely on the basis of the types. In fact, it seems like it's just a design hack to provide a way to access the number of elements in an array without having to introduce a separate operator (or whatever). I find it really ugly, and unnecessarily confusing. Is there any difference (in C) between a constant pointer and an array except for sizeof (and gcc's typeof)?

It's why I tend to jump on people who say that arrays and pointers are equivalent in C/C++.

I've noticed a lot of C programmers are quite fussy about the distinction. Which is why I was surprised that people seemed to use the word array to refer to pointers-used-as-arrays as well (although I guess you always end up with ambiguity when a language has a type named after a generic data type that can be implemented in other ways in the language)

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Sun Jul 15, 2012 10:13 am UTC

I've noticed a lot of C programmers are quite fussy about the distinction. Which is why I was surprised that people seemed to use the word array to refer to pointers-used-as-arrays as well (although I guess you always end up with ambiguity when a language has a type named after a generic data type that can be implemented in other ways in the language)


I think Java contributes quite a bit to the confusion here, because Java arrays are references just like everything else, but use the same kind of syntax, i.e. "int x[20];". In C... it's just not the same. Although it is a huge failing on C's part, in my opinion. Type and variable should be kept distinct, so that "int[20] x, y;" defines two twenty element arrays, and "int* p1, p2" defines two pointers.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Sun Jul 15, 2012 6:00 pm UTC

troyp wrote:I think you're exaggerating, at least - and that's a pretty big "except" you just glossed over. Pointers may be conceptually distinct from arrays in typical usage, but they *can* be used as arrays.

Of course you can use a pointer as if it pointed to an array, because "using a pointer as an array" literally means "add an offset and dereference it". A pointer that points to an array you allocated with malloc isn't any different to a pointer you get any other way, so of course you can assume that every pointer points to an array and use it as such. But that doesn't say anything about any sort of equivalency between the two.

Moreover arrays are implemented like pointers. If "row of houses" actually meant "the address of the first house in the row", then suddenly converting a street address into a row of houses makes a lot more sense (there's just a question of the number of houses, which isn't explicit in either definition or conversion).

This is precisely my point. An array is not a pointer to its first element. The type of "int arr[10]" is "integer array of length 10", not "integer pointer". An arrray is a fixed-length sequence of elements. In certain cases array types in C will implicitly decay to pointers to their first elements - in the similar way that C will implicitly convert an integer to a float. That doesn't make them equal.

Again, pointers are just pointers. An array is a sequence of elements (or just a block of memory if you prefer to think that way). You can't convert a sequence of elements to a pointer or vice versa because that doesn't make sense. But in certain cases if you have an array type, C will be nice enough to give you a pointer to its first element - i.e. the array type will decay to a pointer type for convenience's sake.

Maybe you're saying you *shouldn't* think in those terms, although you can.

No, you can't. Not only does this not work conceptually, it doesn't work in practice either. In C, arrays types and pointer types are not interchangeable in all cases.

But it's clear to me that C programmers do sometimes do this (not sure about C++ programmers). People were just discussing arrays starting at a negative index, where the arrays were actually pointers that were being indexed.

The arrays were not pointers, the pointers pointed to an array (or pointed to some location inside the array for the negative index to work). It's just a pointer into a block of memory. x[-1] is always exactly identical to *(x - 1).

As far as casting an pointer to an array goes, I tried that when I was first learning about arrays (and I was in the middle of wrestling with the compiler about some program). Looking at it now, I can see why the conversion would be problematic. For one thing, an array declaration tells the compiler how many elements the array has, while an pointer-to-array-cast would leave that information missing. You'd have to either provide the information with the cast somehow or make a default assumption (eg. arrays resulting from conversion always have 1 element). Maybe there are other problems, and it wouldn't make sense to allow the cast, or maybe there's actually no scenario where it's really necessary. I don't have a deep understanding a C (read: "I don't even know half the basics"), so it's hard for me to judge. But it's not a *conceptual error* to discuss it.

I feel like I'm repeating myself, but the source of this confusion is precisely because you keep trying to think of pointers as somehow equivalent to arrays. When you say "float arr[10]", C allocates a block of memory large enough to store 10 floats. That's the array. You can ask C, "give me a pointer to the first element in that array" and that makes sense (and that's what C will do for you). You can't say "please convert this integer (a pointer) into a memory block of 10 floats" or vice versa. What is C even supposed to do in that case?

If you actually meant to ask C to convert to "a pointer to the first element" instead of an "array", then you're asking "please convert this pointer to the first element into... a pointer to the first element".

I've noticed a lot of C programmers are quite fussy about the distinction. Which is why I was surprised that people seemed to use the word array to refer to pointers-used-as-arrays as well (although I guess you always end up with ambiguity when a language has a type named after a generic data type that can be implemented in other ways in the language)

People tend to be a bit loose with their terminology but the reason for that is not a lack of understanding, I think. It's just that everyone will understand what you mean when you say "malloc returns an array". Malloc returns a pointer to an array, not an array itself. But there's usually no reason to be this overly precise because everyone knows what you mean.

User avatar
TNorthover
Posts: 191
Joined: Wed May 06, 2009 7:11 am UTC
Location: Cambridge, UK

Re: Coding: Fleeting Thoughts

Postby TNorthover » Sun Jul 15, 2012 7:58 pm UTC

Sc4Freak wrote:I feel like I'm repeating myself, but the source of this confusion is precisely because you keep trying to think of pointers as somehow equivalent to arrays. When you say "float arr[10]", C allocates a block of memory large enough to store 10 floats. That's the array. You can ask C, "give me a pointer to the first element in that array" and that makes sense (and that's what C will do for you). You can't say "please convert this integer (a pointer) into a memory block of 10 floats" or vice versa. What is C even supposed to do in that case?

Code: Select all

*(float (*)[10])&intptr

What the compiler does even in that case is implementation-defined at best, but the result certainly has type float[10]. With -fpermissive GCC allows the more direct "(float[10])intptr", though that's directly against the standard.

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Mon Jul 16, 2012 3:31 am UTC

Sc4Freak wrote:Of course you can use a pointer as if it pointed to an array, because "using a pointer as an array" literally means "add an offset and dereference it". A pointer that points to an array you allocated with malloc isn't any different to a pointer you get any other way, so of course you can assume that every pointer points to an array and use it as such. But that doesn't say anything about any sort of equivalency between the two.

I didn't say they were equivalent. I said they were "mostly interchangeable, but...not in certain cases". That is, that you could use a pointer in most cases in place of an array, or vice versa. I didn't say there *were* the same/equivalent, or even that they almost were. At the start of the conversation, I wasn't clear enough on the details to have an opinion on how similar they ultimately were. I have a clearer picture of the situation now (but I'm not going to offer an opinion at this point, because I can't be bothered having to defend it ;-) )

Moreover arrays are implemented like pointers. If "row of houses" actually meant "the address of the first house in the row", then suddenly converting a street address into a row of houses makes a lot more sense (there's just a question of the number of houses, which isn't explicit in either definition or conversion).

This is precisely my point. An array is not a pointer to its first element. The type of "int arr[10]" is "integer array of length 10", not "integer pointer". An arrray is a fixed-length sequence of elements. In certain cases array types in C will implicitly decay to pointers to their first elements - in the similar way that C will implicitly convert an integer to a float. That doesn't make them equal.

I agree the existence of length information is important - which is why I felt it was necessary to mention it - but as I said, I don't think it renders the very idea of conversion meaningless. If nothing else, you could adopt a default length of 1.

Maybe you're saying you *shouldn't* think in those terms, although you can.

No, you can't. Not only does this not work conceptually, it doesn't work in practice either. In C, arrays types and pointer types are not interchangeable in all cases.

I didn't say they were interchangeable in all cases; I said they weren't. I implied they were *convertible* in all cases (uh, unless the pointer is null, I guess), which is different.

I mean, if I have an array, I can always take a pointer to the first element, right? And if I have a (non-null) pointer, I can always dereference it and place the result in a single-element array? So there's a simple mapping between pointers and arrays - and you can hardly claim it's an arbitrary mapping. That alone is sufficient, in my view, to demonstrate that a conversion is not meaningless.

I should remind you that I don't actually want to convert a pointer to an array. Like I said, I just tried it once when I first learned C arrays and I was struggling with a program. Maybe such a conversion would be pointless. But it's not meaningless.

But it's clear to me that C programmers do sometimes do this (not sure about C++ programmers). People were just discussing arrays starting at a negative index, where the arrays were actually pointers that were being indexed.

The arrays were not pointers, the pointers pointed to an array (or pointed to some location inside the array for the negative index to work). It's just a pointer into a block of memory. x[-1] is always exactly identical to *(x - 1).

You're missing my point. The pointer was *referred to* as an array. Otherwise you wouldn't have an "array beginning at -1". You'd have an "array beginning at 0" and a pointer to its second element used for relative indexing.

Btw, in some cases there is no array declaration, just an allocated block of memory. Do you regard that as an array? You said above you could think of an array as "just a block of memory", but otoh it seems like you regard the type declaration as essential to what an array is (and I don't even disagree until you add 'conceptually'), so I'm not sure if you'd even say there's an array involved in these cases.

As far as casting an pointer to an array goes, I tried that when I was first learning about arrays (and I was in the middle of wrestling with the compiler about some program). Looking at it now, I can see why the conversion would be problematic. For one thing, an array declaration tells the compiler how many elements the array has, while an pointer-to-array-cast would leave that information missing. You'd have to either provide the information with the cast somehow or make a default assumption (eg. arrays resulting from conversion always have 1 element). Maybe there are other problems, and it wouldn't make sense to allow the cast, or maybe there's actually no scenario where it's really necessary. I don't have a deep understanding a C (read: "I don't even know half the basics"), so it's hard for me to judge. But it's not a *conceptual error* to discuss it.

I feel like I'm repeating myself, but the source of this confusion is precisely because you keep trying to think of pointers as somehow equivalent to arrays.

As I said, I'm not thinking pointers are equivalent to arrays, and I don't think I'm confused.

If you mean back when I learned C and I tried to get the cast to work...well, I was confused then. I still knew pointers and arrays weren't the same (since I'd only just read it), but maybe I was confused about their relationship. I understood the *concepts* of arrays and pointers (since they were a.obvious and b.essentially the same as concepts I was already familiar with), but I was definitely a bit hazy on the details of the type system (I don't think I'd ever used a statically-typed language before). So maybe that's why I tried to do it. Tbh, I don't know if I thought the matter through more than "I need to trick the compiler into accepting this".
When you say "float arr[10]", C allocates a block of memory large enough to store 10 floats. That's the array. You can ask C, "give me a pointer to the first element in that array" and that makes sense (and that's what C will do for you). You can't say "please convert this integer (a pointer) into a memory block of 10 floats" or vice versa. What is C even supposed to do in that case?

I don't have any (sensible) suggestion. Can you suggest how an integer should be converted into a float ending in ".345"? Does that mean it's meaningless to convert an int into a float? To be meaningful, a conversion must be able to map *from* anything, not *to* anything.

I know how to meaningfully convert your int address into a block of *one* float. And I'm sure you do too.

I've noticed a lot of C programmers are quite fussy about the distinction. Which is why I was surprised that people seemed to use the word array to refer to pointers-used-as-arrays as well (although I guess you always end up with ambiguity when a language has a type named after a generic data type that can be implemented in other ways in the language)

People tend to be a bit loose with their terminology but the reason for that is not a lack of understanding, I think. It's just that everyone will understand what you mean when you say "malloc returns an array". Malloc returns a pointer to an array, not an array itself. But there's usually no reason to be this overly precise because everyone knows what you mean.

Oh, I didn't think they were misunderstanding anything. I was just unclear about how terminology was used. I'm sure experienced C programmers know what one other mean, but it was a bit confusing to me when I was unsure how words were being used.

User avatar
PM 2Ring
Posts: 3700
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Coding: Fleeting Thoughts

Postby PM 2Ring » Mon Jul 16, 2012 5:20 am UTC

Sc4Freak wrote:This is precisely my point. An array is not a pointer to its first element. The type of "int arr[10]" is "integer array of length 10", not "integer pointer". An array is a fixed-length sequence of elements. In certain cases array types in C will implicitly decay to pointers to their first elements - in the similar way that C will implicitly convert an integer to a float. That doesn't make them equal.

Again, pointers are just pointers. An array is a sequence of elements (or just a block of memory if you prefer to think that way). You can't convert a sequence of elements to a pointer or vice versa because that doesn't make sense. But in certain cases if you have an array type, C will be nice enough to give you a pointer to its first element - i.e. the array type will decay to a pointer type for convenience's sake.

[...]

People tend to be a bit loose with their terminology but the reason for that is not a lack of understanding, I think. It's just that everyone will understand what you mean when you say "malloc returns an array". Malloc returns a pointer to an array, not an array itself. But there's usually no reason to be this overly precise because everyone knows what you mean.


Yeah. I guess it's a Good Idea in discussions like this to be precise with the terminology. I was a bit sloppy above saying "A C array variable is essentially a constant pointer to the zeroth element of the array." But I assumed that it was obvious that a sequence of elements is not the same thing as the address of that sequence. And I hoped that my K&R quote made things more clear: "the name of an array is a synonym for the location of the initial element".


On the importance of distinguishing between a thing and its name:
Lewis Carroll wrote:The name of the song is called 'Haddocks' Eyes.'"

"Oh, that's the name of the song, is it?" Alice said, trying to feel interested.

"No, you don't understand," the Knight said, looking a little vexed. "That's what the name
is called. The name really is 'The Aged, Aged Man.'"

"Then I ought to have said 'That's what the song is called'?" Alice corrected herself.

"No you oughtn't: that's another thing. The song is called 'Ways and Means' but that's only
what it's called, you know!"

"Well, what is the song then?" said Alice, who was by this time completely bewildered.

"I was coming to that," the Knight said. "The song really is 'A-sitting On a Gate': and the
tune's my own invention."
- Alice Through The Looking Glass

User avatar
PM 2Ring
Posts: 3700
Joined: Mon Jan 26, 2009 3:19 pm UTC
Location: Sydney, Australia

Re: Coding: Fleeting Thoughts

Postby PM 2Ring » Mon Jul 16, 2012 5:36 am UTC

TNorthover wrote:

Code: Select all

*(float (*)[10])&intptr

What the compiler does even in that case is implementation-defined at best, but the result certainly has type float[10].

With -fpermissive GCC allows the more direct "(float[10])intptr", though that's directly against the standard.

Yipes! That second example is scary. IMHO, the compiler shouldn't encourage you to do weird shit like that, and if you really want to do that sort of thing you ought to do it via pointers, as in your first example.

But I will admit that I've used casts to do funny conversions, eg converting an array of 4 chars into a 32 bit unsigned integer, when processing IFF chunk ID types on the Amiga.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Mon Jul 16, 2012 2:21 pm UTC

So I stumbled onto this today: http://blog.regehr.org/archives/161

I'm afraid now.
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
Xanthir
My HERO!!!
Posts: 5400
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: Coding: Fleeting Thoughts

Postby Xanthir » Mon Jul 16, 2012 5:24 pm UTC

You, sir, name? wrote:So I stumbled onto this today: http://blog.regehr.org/archives/161

I'm afraid now.

Summary for those who don't want to read a long post: in some circumstances, C compilers are allowed to compile a loop out, even if it would be an infinite loop. This includes cases where *theoretically* it might not be infinite, and might return a value in some cases, such as a search for a counter-example to some simple mathematical conjecture. (The blog post uses a loop that searches for counter-examples to Fermat's Last Theorem, which has been proven true, but you could swap in an unproven conjecture like Goldbach's if you want a loop that could theoretically return a result.)

The author disagrees with this semantic.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

troyp
Posts: 557
Joined: Thu May 22, 2008 9:20 pm UTC
Location: Lismore, NSW

Re: Coding: Fleeting Thoughts

Postby troyp » Tue Jul 17, 2012 12:15 am UTC

From the original post:
Embedded in Academia wrote:The implication, of course, is that the compiler has disproved Fermat’s Last Theorem. Faced with this incredible mathematical discovery, I held my breath and added a line of code at the end of the function to print the counterexample: the values of a, b, and c. Unfortunately, with their bluffs called in this fashion, all of the compilers emitted code that actually performed the requested computation, which of course does not terminate. I got the feeling that these tools — like Fermat himself — had not enough room in the margin to explain their reasoning.

lol

Xanthir wrote:Summary for those who don't want to read a long post: in some circumstances, C compilers are allowed to compile a loop out, even if it would be an infinite loop.

Are they allowed to, or do they just do it anyway for performance?
The author says (in an update to the first post):
Embedded in Academia wrote:The compiler is given considerable freedom in how it implements the C program, but its output must have the same externally visible behavior that the program would have when interpreted by the “C abstract machine” that is described in the standard. Many knowledgeable people (including me) read this as saying that the termination behavior of a program must not be changed. Obviously some compiler writers disagree, or else don’t believe that it matters. The fact that reasonable people disagree on the interpretation would seem to indicate that the C standard is flawed. In contrast, the Java language definition is quite clear that infinite loops may not be terminated by the JVM.

The obvious interpretation is that termination is "externally visible behaviour" (I mean, you observe it just by running the program). From a naieve perspective at least.

jareds
Posts: 436
Joined: Wed Jan 03, 2007 3:56 pm UTC

Re: Coding: Fleeting Thoughts

Postby jareds » Tue Jul 17, 2012 4:56 am UTC

In my view, there is no reasonable argument that printing "Fermat's Last Theorem has been disproved" is a legal compilation of the given C program (prior to C11, where it is legal for one of his examples but not the other). The compilers that did so were simply wrong, and this cannot be reasonably attributed to an ambiguity in the standard. The author's argument to the contrary is based on hyper-formal readings of the relevant part of the standard. The standard is not a formal semantics, and any attempt to interpret it is such is doomed to find countless ambiguities.

The C99 standard says, "At program termination, all data written into files shall be identical to the result that execution of the program according to the abstract semantics would have produced." The author says that this is vacuously true if the program doesn't terminate in the abstract semantics and "program termination" is interpreted to mean "program termination according to the abstract semantics". However, the sentence doesn't even make sense that way: "At program termination [according to the abstract semantics], all data written into files [in the actual execution]"; what?? "All data written into files" must refer to actual execution or the whole sentence is vacuous. "At program termination" then serves as a temporal modifier for the actual execution. stdout is a file, so this prohibits writing "FLT has been disproven" to stdout.

The C99 standard says, "The input and output dynamics of interactive devices shall take place as specified in 7.19.3." The author says that this requirement is met because "nothing surprising relating to termination is found in 7.19.3". With all due respect, this is completely nuts. Can this program print "hello"?

Code: Select all

int main() {
if (0 == 1) printf("hello\n");
return 0;
}
After all, nothing whatsoever about "if" statements can be found in 7.19.3. Of course, the sane interpretation of the statement is, "The input and output dynamics of interactive devices shall be consistent with execution according to the abstract semantics, with attention drawn to 7.19.3." (which talks about buffering of I/O, including interactive devices).

Now, this is all sort of moot, since C11 and C++11 explicitly address the topic (for better or worse). In C11, an iteration statement whose controlling expression is not a constant expression (or omitted controlling expression in a for statement) and which does not do any I/O, volatile accesses, synchronization, or atomic operations, can be assumed by the implementation to terminate. C++11 makes no exception for constant controlling expressions, and in fact states that every thread may be assumed to eventually do one of those listed things or terminate. Clearly, the C++ committee is not trying to keep the language suitable for systems programming, which is where you'll find the common valid use case of a simple non-terminating do-nothing loop, which would of course be controlled by a constant expression.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Tue Jul 17, 2012 7:04 am UTC

A simple use case for a non-terminating loop. Though it may provoke a chuckle, the point should be obvious: code execution always has side-effects. As a functional programmer, I like to pretend otherwise, and in the vast majority of the cases it's fine to reason in such a manner. But not always. Because a running process uses system resources, it has an observable effect. A "do nothing infinite loop" can be checked to make sure it's still running or killed by another process. So the semantic "bottom" value ought to be respected. Though, of course, a reasonable compiler should still detect the situation and raise a warning.

User avatar
Link
Posts: 1399
Joined: Sat Mar 07, 2009 11:33 am UTC
Location: ᘝᓄᘈᖉᐣ
Contact:

Re: Coding: Fleeting Thoughts

Postby Link » Tue Jul 17, 2012 9:00 am UTC

One of the things I have repeatedly been told about programming is that the computer does what you tell it to, and frankly, I find the idea that compilers can just do something else without being completely certain that the end result is absolutely, unquestionably, provably the same, rather disgusting. When I say "keep doing this until you are killed by an external condition", I most definitely don't mean "don't do this at all". In fact, one of the reasons I might employ an infinite loop is to ensure that the program never reaches the following code.

If someone finds a case where the compiler makes a wrong assumption, then making the assumption at all is, in my opinion, a bug. If the standard specifies that the assumption is right, without providing a sane way to get the expected result, then I'd simply call it a bad standard.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11115
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Tue Jul 17, 2012 2:33 pm UTC

jareds wrote:Now, this is all sort of moot, since C11 and C++11 explicitly address the topic (for better or worse). In C11, an iteration statement whose controlling expression is not a constant expression (or omitted controlling expression in a for statement) and which does not do any I/O, volatile accesses, synchronization, or atomic operations, can be assumed by the implementation to terminate. C++11 makes no exception for constant controlling expressions, and in fact states that every thread may be assumed to eventually do one of those listed things or terminate. Clearly, the C++ committee is not trying to keep the language suitable for systems programming, which is where you'll find the common valid use case of a simple non-terminating do-nothing loop, which would of course be controlled by a constant expression.
What is that common case? More explicitly, if you please.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

Ubik
Posts: 1016
Joined: Thu Oct 18, 2007 3:43 pm UTC

Re: Coding: Fleeting Thoughts

Postby Ubik » Tue Jul 17, 2012 2:55 pm UTC

My guess would be timing, or specifically pausing things with busy loops.

Edit: As to why that's my guess, is because of a Linux audio problem I had. Here's link to a patch that's supposed to help with the problem of sound not working after waking computer up from sleep. This is the essential part:

Code: Select all

+   for (tries = 0; tries < 3; tries++) {
+      rem = snd_cmipci_read_w(cm, reg);
+      if (rem < rec->dma_size)
+         goto ok;
+   }

That isn't an example of the thing, but I found out that that workaround (wait in loop for a few rounds until a pointer is within a valid range) doesn't work too well. When I looked deeper into how to help this (including simply increasing the number of tries), I found out about some functions / macros in Linux kernel that allow causing very short pauses, and even though I didn't look into their implementation, I think I read that they work by looping a number of cycles.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Tue Jul 17, 2012 3:55 pm UTC

Link wrote:One of the things I have repeatedly been told about programming is that the computer does what you tell it to, and frankly, I find the idea that compilers can just do something else without being completely certain that the end result is absolutely, unquestionably, provably the same, rather disgusting. When I say "keep doing this until you are killed by an external condition", I most definitely don't mean "don't do this at all". In fact, one of the reasons I might employ an infinite loop is to ensure that the program never reaches the following code.

If someone finds a case where the compiler makes a wrong assumption, then making the assumption at all is, in my opinion, a bug. If the standard specifies that the assumption is right, without providing a sane way to get the expected result, then I'd simply call it a bad standard.


Yeah, exactly. This type of code is there for a reason. Redundant code is typically glaringly obvious. And even if it's obscure, the sensible thing would be to have the compiler warn about this so that the programmer can determine if it's a mistake, rather than just summarily discarding it as junk.
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: Coding: Fleeting Thoughts

Postby Sc4Freak » Tue Jul 17, 2012 5:22 pm UTC

These decisions are hardly ever so black and white. You've essentially got the choice between making some small corner cases work, versus making all code run faster. I daresay say the C++ standards committee absolutely made the right decision here. If you really need a loop that cannot be optimized out, then the standard already guarantees that the optimization can be trivially bypassed (just write to a volatile variable or something mundane like that). But the increased ease in code analysis means that every compiled program can now run faster because of better compiler optimizations. Given the choice between making all code faster at the cost of a trivial workaround for corner-case loops, versus slower code for everyone, I'll take the first option.

Besides, it's not like this is the first time the as-if rule has been broken. The compiler is also allowed to elide copy constructors in certain cases to optimize function returns. If you have a copy constructor with side effects this will break your code, but likewise that corner case was sacrificed to provide better performance for everyone.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Tue Jul 17, 2012 6:56 pm UTC

Allowing crazy shit in edge cases is kind of a fundamental part of C++. One of the philosophies used when creating C++ was that it should give the programmer a choice, even if that means he can choose wrong. If I can't really choose to have a do-nothing loop without a hack, then I don't think the standard is adhering to that philosophy.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11115
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Tue Jul 17, 2012 8:20 pm UTC

Ubik wrote:My guess would be timing, or specifically pausing things with busy loops.

Sure. Except:
volatile accesses
is one exception to "all loops are presumed to exit".

Non-volatile access to memory can, in C++, be optimized out. So long as you can make sure (in the abstract model) that nobody changes it between the two accesses.
Link wrote:When I say "keep doing this until you are killed by an external condition"
The C++ clause requires "this" to be "basically nothing". Either that, you are treating what is actually volatile memory access (either here, or elsewhere) as non-volatile. Because if you are accessing volatile memory, the "loop skipping" assumption goes away.

Volatile memory being memory that another thread of execution, or hardware somewhere, could read or write outside of your thread of execution. That the C++ abstract machine isn't allowed to presume evolves in a locally deterministic manner.

Lacking that keyword, C++ allows compilers to presume local determinism.

So, is there a case other than "I want this thread to halt until killed"? There is also "I want to waste some time here, doing nothing", but in that case the assumption that the loop will finish is a valid assumption, right?
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

jareds
Posts: 436
Joined: Wed Jan 03, 2007 3:56 pm UTC

Re: Coding: Fleeting Thoughts

Postby jareds » Wed Jul 18, 2012 3:04 am UTC

Yakk wrote:What is that common case? More explicitly, if you please.

I didn't phrase that quite right. I only meant "common" case as opposed to contrived cases like searching for a counterexample to Goldbach's conjecture.

In any event, here are two major examples (recall I am talking about systems programming, not application programming):

1. On a device without a low-power state, there is nothing left to do for now but spin and wait for a timer interrupt.

2. In an assert/panic handler with no OS or within the OS, spin at the end of the handler (rather than charge ahead doing garbage).

Obviously, it is trivial to write a non-terminating do-nothing loop in C++11 using a volatile. However, this means nothing for existing code.

I'm not even going so far as to say this is a bad decision in practice. In my own experience, I'm not aware of any such examples being written in C++ rather than C. However, if the C++ committee is willing to break systems code written in C++, that goes in the "con" column when deciding whether to write systems code in C++ in the future.

Link wrote:One of the things I have repeatedly been told about programming is that the computer does what you tell it to, and frankly, I find the idea that compilers can just do something else without being completely certain that the end result is absolutely, unquestionably, provably the same, rather disgusting. When I say "keep doing this until you are killed by an external condition", I most definitely don't mean "don't do this at all". In fact, one of the reasons I might employ an infinite loop is to ensure that the program never reaches the following code.

If someone finds a case where the compiler makes a wrong assumption, then making the assumption at all is, in my opinion, a bug. If the standard specifies that the assumption is right, without providing a sane way to get the expected result, then I'd simply call it a bad standard.

No, no, no, no, no! This is the attitude that leads to my "God kills a kitten" example from page 105 of this thread. If you want a high-level assembler rather than a compiler, then turn off optimizations, or declare everything as volatile, or something like that. In C or C++, essentially no memory optimizations are possible if the programmer is allowed to assume that optimizations don't change the program no matter what, so you won't even lose anything by doing as I sarcastically suggest.

User avatar
Link
Posts: 1399
Joined: Sat Mar 07, 2009 11:33 am UTC
Location: ᘝᓄᘈᖉᐣ
Contact:

Re: Coding: Fleeting Thoughts

Postby Link » Wed Jul 18, 2012 8:13 am UTC

Sc4Freak wrote:If you really need a loop that cannot be optimized out, then the standard already guarantees that the optimization can be trivially bypassed (just write to a volatile variable or something mundane like that).

That would work, of course, but it's a kludge (you're not passing meaningful data to/reading meaningful data from other threads or hardware; you just want to tag a loop as potentially infinite). It generally bothers me when a standard requires a kludge like that. It's also possible to get faster code in general while still supporting these corner cases, at the cost of increased compile time (i.e. through more complicated analysis). Personally, I'd prefer that.

Yakk wrote:So, is there a case other than "I want this thread to halt until killed"? There is also "I want to waste some time here, doing nothing", but in that case the assumption that the loop will finish is a valid assumption, right?
Well, the Fermat counterexample is a special case of the first one: "I want this thread to halt until killed OR a certain condition occurs". That condition does not require exchanging any data between threads or hardware. It can be optimised out if the compiler can work out whether the condition can occur at all, but the correct optimised version of the Fermat counterexample, then, would be the trivial infinite loop.

jareds wrote:No, no, no, no, no! This is the attitude that leads to my "God kills a kitten" example from page 105 of this thread. If you want a high-level assembler rather than a compiler, then turn off optimizations, or declare everything as volatile, or something like that.
I can see where you're coming from, but I think neither "turn off all optimisation" nor "use a kludge to trick the compiler into doing what you want" are good solutions. It's difficult to find a middle ground, but to me, something like adding a preprocessor directive to the standard to prevent the compiler making certain assumptions about the following block would be more acceptable than requiring not-quite-obvious kludges like accessing a volatile variable. Perhaps something like this:

Code: Select all

#opt !assume(halts)
while (...)
{
    ...
}

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Wed Jul 18, 2012 8:41 am UTC

Or a compiler option that turns of halting assumptions.

As much as I like the idea that the computer should do exactly what you tell it to, a lot of impressive optimization wouldn't be possible were that the case. Also there wouldn't be garbage collection, but I don't care too much about that.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Wed Jul 18, 2012 10:46 am UTC

sourmìlk wrote:Also there wouldn't be garbage collection, but I don't care too much about that.

Try it and you will. Garbage collection is for people too lazy to reason about the lifespan of memory. Erm, no. The jump to GC code is every bit as significant as from assembler to structured languages.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Wed Jul 18, 2012 12:46 pm UTC

I guess it would speed up some software.
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11115
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed Jul 18, 2012 2:08 pm UTC

Well, the Fermat counterexample is a special case of the first one: "I want this thread to halt until killed OR a certain condition occurs". That condition does not require exchanging any data between threads or hardware. It can be optimised out if the compiler can work out whether the condition can occur at all, but the correct optimised version of the Fermat counterexample, then, would be the trivial infinite loop.

Note that hardware includes memory.

Including or requiring to include arbitrary theorem provers to optimize code is unreasonable.

The only possibilities is that the loop provably does not halt, the execution thread terminates before it halts, or the thread halts.

The before case would require no optimization anywhere.

That leaves halting and non halting. So your idea is to require a formal proof by the compiler on every loop before the compiler can assume it halts? In practice that makes that kind of optimization impossible, but maybe that is OK with you.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Wed Jul 18, 2012 2:57 pm UTC

Link wrote:
jareds wrote:No, no, no, no, no! This is the attitude that leads to my "God kills a kitten" example from page 105 of this thread. If you want a high-level assembler rather than a compiler, then turn off optimizations, or declare everything as volatile, or something like that.
I can see where you're coming from, but I think neither "turn off all optimisation" nor "use a kludge to trick the compiler into doing what you want" are good solutions. It's difficult to find a middle ground, but to me, something like adding a preprocessor directive to the standard to prevent the compiler making certain assumptions about the following block would be more acceptable than requiring not-quite-obvious kludges like accessing a volatile variable. Perhaps something like this:

Code: Select all

#opt !assume(halts)
while (...)
{
    ...
}


Or just add a loop modifier. Something like

Code: Select all

volatile for (;;) ;


Makes so much more sense than

Code: Select all

volatile int i = 0;
while (!i) ;
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: Coding: Fleeting Thoughts

Postby sourmìlk » Thu Jul 19, 2012 5:38 am UTC

Ben-oni wrote:
sourmìlk wrote:Also there wouldn't be garbage collection, but I don't care too much about that.

Try it and you will. Garbage collection is for people too lazy to reason about the lifespan of memory. Erm, no. The jump to GC code is every bit as significant as from assembler to structured languages.


I'm not saying that GC is objectively worse, just that I don't prefer it. I've used garbarge collected and unmanaged* languages, and I prefer the ones that require memory management just because I like to know where everything is. Garbage collection isn't worse, it's just different in a way I don't find particularly appealing.

* - unmanaged ones are the ones without garbage collection, right? For no good reason I always forget which is which.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
Bubbles McCoy
Posts: 1106
Joined: Wed Jul 09, 2008 12:49 am UTC
Location: California

Re: Coding: Fleeting Thoughts

Postby Bubbles McCoy » Thu Jul 19, 2012 7:45 pm UTC

sourmìlk wrote:I'm not saying that GC is objectively worse, just that I don't prefer it. I've used garbarge collected and unmanaged* languages, and I prefer the ones that require memory management just because I like to know where everything is. Garbage collection isn't worse, it's just different in a way I don't find particularly appealing.

* - unmanaged ones are the ones without garbage collection, right? For no good reason I always forget which is which.

I believe managed code typically includes garbage collection, but I don't think the division is quite right - natively run code could have gc cooked into it.

Anyway, not trying to be mean here, but I sense a general theme in your posts that you care far more about how the code makes you feel rather than the quality and maintainability of your product. I guess this isn't a super serious problem so long as your coding for the pure pleasure of it, but this kind of attitude can be kinda detrimental on the whole. Garbage collection makes it a whole lot easier to work quickly (and adapt other's work quickly), which makes it invaluable in most situations.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11115
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Thu Jul 19, 2012 8:17 pm UTC

My issue with GC is that it isn't reproducible by the user of the language usually. GC causes hugely non-deterministic behavior in many cases, and can easily lead to leaks as bad or worse than non-GC code.

It does make it harder to dereference a deallocated resource.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Thu Jul 19, 2012 8:18 pm UTC

There are very valid reasons to dislike the behind-the-sceneiness of GC. As recently discussed in this thread, you have to go to fairly ridiculous lengths to avoid GC when dealing with timing critical high-throughput systems. Careless memory allocation leads to what is effectively the same as a memory leak, where instead of running out of memory GC is triggered (which might as well be the same thing).

The only reasons these types of applications use garbage collecting languages is that the same languages are much more fault tolerant than most non-GC:ing languages.
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11115
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Thu Jul 19, 2012 8:32 pm UTC

Yes.

What I want is a C/C++ level language with the ability to do compile time introspection of class type structures, and metaclasses of classes with access to that.

So I can say "GarbageCollected class foo", which causes compile-time parsing of the methods/variables of foo. It can, for example, check that each data member of foo is also GarbageCollected. Similarly, when the foo type is used (not the instances, the type), it can validate the context (so raw pointers to foo aren't allowed). In effect, I want to be able to in-language have enough power to create a Java/C# esque "managed" typesystem.

Similarly, I want to be able to say "Reflecting class foo", and have it make the members of foo Reflect. Or "Property class foo", and when I create Property members their access has implicit access to the this pointer (in effect, I modify both code in foo, and code that uses foo). But I want this to happen with zero run-time cost, a modest compile-time cost, and with a system strong enough to do these kind of things in the language without it being a bunch of hard-coded keywords that only do this (because I don't know what else could be done this way..).

Then I can have a GC GUI low-performance reflectable system embedded adjacent to my high-performance audio filtering, without having to deal with crossing a language barrier half way.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

Ben-oni
Posts: 278
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: Coding: Fleeting Thoughts

Postby Ben-oni » Thu Jul 19, 2012 8:58 pm UTC

Yakk wrote:Yes.

What I want is a C/C++ level language with the ability to do compile time introspection of class type structures, and metaclasses of classes with access to that.

So I can say "GarbageCollected class foo", which causes compile-time parsing of the methods/variables of foo. It can, for example, check that each data member of foo is also GarbageCollected. Similarly, when the foo type is used (not the instances, the type), it can validate the context (so raw pointers to foo aren't allowed). In effect, I want to be able to in-language have enough power to create a Java/C# esque "managed" typesystem.

Similarly, I want to be able to say "Reflecting class foo", and have it make the members of foo Reflect. Or "Property class foo", and when I create Property members their access has implicit access to the this pointer (in effect, I modify both code in foo, and code that uses foo). But I want this to happen with zero run-time cost, a modest compile-time cost, and with a system strong enough to do these kind of things in the language without it being a bunch of hard-coded keywords that only do this (because I don't know what else could be done this way..).

Then I can have a GC GUI low-performance reflectable system embedded adjacent to my high-performance audio filtering, without having to deal with crossing a language barrier half way.


It's called Common Lisp, and it already exists. Just as CL gives the programmer direct control over the parser, compiler, and interpreter, it also gives the programmer good control over the garbage collector as well. And because it's Lisp, you can get an unlimited level of reflection when you want it. CL is low-level (comparable to C) when you want it to be, and high-level when you need it to be. Just because the basic data structure of the language is the (GC managed) cons cell doesn't mean you have to use them at runtime.

User avatar
You, sir, name?
Posts: 6983
Joined: Sun Apr 22, 2007 10:07 am UTC
Location: Chako Paul City
Contact:

Re: Coding: Fleeting Thoughts

Postby You, sir, name? » Thu Jul 19, 2012 9:01 pm UTC

When lisp can do real time audio processing, I'm willing to consider it an option.
I edit my posts a lot and sometimes the words wrong order words appear in sentences get messed up.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 17 guests